万丈高楼平地起---String类

简介: 关于java的String类

技术的精进需要扎实的基础!今天我们就来看一下String类

我们都知道,字符串是十分重要的的,为此,Java专门提供了一种String类。

String的构造方法
1、直接进行初始化

2、new String对象

3、通过char数组进行构造

public static void main(String[] args) {

String str1 = "stay";
String str2 = new String("stay");
char[] ch = {'s', 't', 'a', 'y'};
String str3 = new String(ch);
System.out.println(str1);
System.out.println(str2);
System.out.println(str3);

复制代码
那么String类内部究竟是有哪些组成的呢?

查看源码并通过编译就可以知道

image-20220528103353283

image-20220528103426958

String类里面存储的是char类型的value数组以及hash

image-20220528103846242

String是引用类型,里面存储的是地址

求字符串的长度
直接字符串名.length()

public static void main(String[] args) {

String str1 = "stay";
System.out.println(str1.length());

int[] arr = {1, 2, 3, 4};
System.out.println(arr.length);

}
复制代码
需要注意的是,字符串里面的length是方法,要加上括号,而求数组的长度时,length是数组本身的属性,不需要加上括号

字符串的比较
1、字符串名==字符串名进行地址比较

2、equals()与equalsIgnoreCase()进行内容比较

3、compareTo()与compareToIgnoreCase()进行大小比较

public static void main(String[] args) {

String str1 = new String("hello");
String str2 = new String("Hello");
System.out.println(str1 == str2);//str里面存放的是地址,new了两个不一样的对象,地址一定就不一样,所以输出结果是false
System.out.println(str1.equals(str2));//equals比较的是字符串的内容
System.out.println(str1.equalsIgnoreCase(str2));//忽略大小写比较字符串的内容
 System.out.println(str1.compareTo(str2));//调用compareTo方法,比较字符串的大小。要是str1大于str2就返回正数,否则返回负数
System.out.println(str1.compareToIgnoreCase(str2));//使用compareToIgnoreCase就会忽略大小写进行比较 

}
复制代码
字符串的查找
1、chaeAt()可以得到对应下标的字符

2、indexOf()用来会返回某个字符或者某个字符串首次出现的下标,要是找不到就返回-1

3、lastIndexOf从后往前找,先找到对应的字符再返回下标

public static void main(String[] args) {

String s1 = "stay hungry";
for (int i = 0; i < s1.length(); i++) {
    char ch = s1.charAt(i);
    System.out.print(ch + " ");
}
System.out.println();

int index = s1.indexOf('h');
System.out.println(index);//5
int index2 = s1.indexOf('g', 2);//从下标为2的位置开始查找
System.out.println(index2);//8
int index3 = s1.indexOf("hu");
System.out.println(index3);//5

}
复制代码
public static void main(String[] args) {

String str = "ababaryth"
int n = str.lastIndexOf('t');
System.out.println(n);//7
int n2 = str.lastIndexOf('a', 3);//从abab开始向前找
System.out.println(n2);//2

}
复制代码
转化
1、数字转化为字符串
public static void main(String[] args) {

String str = String.valueOf(123);
System.out.println(str);//123

}
复制代码
另外,还可以将类也变成字符串

class Stu{

public int ID;

public Stu(int ID) {
    this.ID = ID;
}

@Override
public String toString() {
    return "Stu{" +
            "ID=" + ID +
            '}';
}

}
public class Test {

public static void main(String[] args) {
    String str = String.valueOf(new Stu(12345));
    System.out.println(str);
}

}
//Stu{ID=12345}
复制代码
将字符串转化为数字(可以使用进制)

public static void main(String[] args) {

int a = Integer.valueOf("12", 8);//按照八进制进行转化
System.out.println(a);
//10
 int b = Integer.parseInt("1234");
 System.out.println(b);
//10
//Integer.valueOf和Integer.parseInt都是一样的

复制代码
在常量池里面相同的字符串只会存在一份

字符 字节 字符串的关系

2、字符与字符串
字符转化为字符串
public static void main(String[] args) {

char[] val = {'a', 'b', 'c', 'd' };
String str = new String(val);
System.out.println(str);//abcd

String str2=new String(val,1,2);//偏移量是1,数量是2
System.out.println(str2);//bc

}
复制代码
字符串转化为字符
public static void main(String[] args) {

String str1 = "hungry";
char ch = str1.charAt(3);//输出偏移量(offset)(下标)为3的字母
System.out.println(ch);//g


char[] val2 = str1.toCharArray();//将字符串变为数组
System.out.println(Arrays.toString(val2));

}
复制代码
判断一个字符串是不是全是由数字组成的?
public static boolean IsNum(String str){

for (int i = 0; i < str.length(); i++) {
    char ch = str.charAt(i);//获得数组的每一个元素
    if (ch < '0' || ch > '9') {
        return false;
    }

}
return true;

}
//判断一个字符串中是不是全部都是数字
public static void main(String[] args) {

String str = "12345";
boolean flg = IsNum(str);
System.out.println(flg);

}
复制代码
3、字节与字符串
将字节转化为字符串
public static void main(String[] args) {

byte[] e = {100, 101, 102,103};
String str = new String(e);
System.out.println(str);//defg
String str2 = new String(e,1,2);//偏移量(offset)为1,数量为2
System.out.println(str2);//ef

}
复制代码
将字符串转化为字节
public static void main(String[] args) {

String str = "hello";
byte[] e = str.getBytes();
System.out.println(Arrays.toString(e));

}
复制代码
将字符串转化为一个字符数组
public static void main(String[] args) {

String s1 = "stay hungry";
char[] ch = s1.toCharArray();
for (char x : ch) {
    System.out.println(x);
}

}
//并不会改变s1,只是创建了一个新的对象
复制代码
格式化
public static void main(String[] args) {

String s1 = String.format("%d %d %d", 2021, 5, 31);
System.out.println(s1);

}
//2021 5 31
复制代码
下面就要介绍一下

equals是否区分大小写的两种方法
public static void main(String[] args) {

String str1 = "Hello";
String str2 = "hello";
System.out.println(str1.equals(str2));//严格区分大小写
System.out.println(str1.equalsIgnoreCase(str2));//不进行大小写区分

}
复制代码
比较两个字符串的大小
public static void main(String[] args) {

String str1 = "Hello";
String str2 = "Hell";
System.out.println(str1.compareTo(str2));

}
//String里面已经重写了compareTo方法
//要是str1大于str2就返回正数,否则就返回负数
复制代码
字符串的替换
public static void main(String[] args) {

String str1 = "Hellooth";
String str2 = str1.replace('H', 'k');//将所有的H替换成K
System.out.println(str2);
System.out.println("=======================");
String str3 = str1.replace("ll", "yy");
System.out.println(str3);
System.out.println("=======================");
String str4="shoopeoohe";
String str5=str4.replaceFirst("oo","uk");
System.out.println(str5);

}
//replace既可以替换单个字符,也可以替换字符串(替换所有的字符串)
//replaceFirst会替换第一次出现的单个字符或者字符串
复制代码
字符串的截取
public static void main(String[] args) {

String str1 = "Hellooth";
String ret = str1.substring(1);//从下标为1处开始往后截取
System.out.println(ret);//ellooth
String ret2 = str1.substring(1,3);//左闭右开
System.out.println(ret2);//el

}
复制代码
消去字符串的左右空格trim
public static void main(String[] args) {
String str1 = " He llooth ";

String ret = str1.trim();
System.out.println(ret);

}
//He llooth
//只能消去左右两侧的空格,但是不能消去字符串中间的空格
复制代码
修改字符的大小写
public static void main(String[] args) {

String s1 = "hello";
String ret = s1.toUpperCase();
System.out.println(ret);

String s2 = "HELLO";
String ret2 = s2.toLowerCase();
System.out.println(ret2);
System.out.println("s2:" + s2);

}
//HELLO
//hello
//s2:HELLO 也就是说toUpperCase和toLowerCase并不会改变原来的字符串的值,它新创造了一个字符串
复制代码
字符串的拆分
public static void main(String[] args) {

String s1 = "welcome to the world";
String[] ret = s1.split(" ");//以空格为拆分的标识
for (String x : ret) {
    System.out.println(x);
}

}
//welcome
//to
//the
//world
复制代码
这个split方法是有重载的,也可以传两个参数,第二个参数表示最多拆分成几组

public static void main(String[] args) {

String s1 = "welcome to the world";
String[] ret = s1.split(" ",3);
for (String x : ret) {
    System.out.println(x);
}

}
//welcome
//to
//the world
复制代码
字符串拆分的一些特例
字符"|","*","+"都得加上转义字符,前面加上"\" .
而如果是" 斜杠 " ,那么就得写成"\" .
如果一个字符串中有多个分隔符,可以用"|"作为连字符.
public static void main(String[] args) {

String s1 = "123.45.1.1";
String[] ret= s1.split("\\.");//两个斜杠表示真正的斜杠
for (String x : ret) {
    System.out.println(x);
}

复制代码
public static void main(String[] args) {

String s1 = "123\\45\\1\\1";//要是只写一个斜杆就会被转义,所以就写成了两个斜杠
String[] ret= s1.split("\\\\");//四个斜杠其实就是两个真正的斜杠
for (String x : ret) {
    System.out.println(x);
}

复制代码
要是有多个分隔符,就可以使用 | 进行了分隔

public static void main(String[] args) {

String s1 = "zhangsan wangwu&lisi";
String[] ret = s1.split(" |&");//以空格和&进行分隔
for (String x : ret) {
    System.out.println(x);
}

}
//zhangsan
//wangwu
//lisi
复制代码
多次拆分
public static void main(String[] args) {

String s1 = "zhangsan=wangwu&yes=lisi";
String[] ret = s1.split("&");//先拆分成两个部分
for (String x : ret) {
    String[] x2 = x.split("=");//再进行拆分
    for (String ret2 : x2) {
        System.out.println(ret2);
    }
}

}
//zhangsan
//wangwu
//yes
//lisi
复制代码
字符串常量池
我们首先要知道什么是池?

"池" 是编程中的一种常见的, 重要的提升效率的方式, 特点就是随用随取,可以提高代码运行效率

常见的池包括Class文件常量池、运行时常量池、字符常量池……

public static void main(String[] args) {

String s1 = "stay";
String s2 = "stay";
System.out.println(s1 == s2);//运行结果是true

}
复制代码
image-20220531212323855

判断s1==s2时,会先去常量池里面看一下有没有相同的字符串,要是有就不会进行创建,直接使用同一份对象,要是没有就创建一份

public static void main(String[] args) {
String s1 = "stay";
String s2 = "stay";
String s3=new String ("hello");
System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//false
}
复制代码
image-20220531213429877

s1与s3指向不同的对象,里面存的是不一样的地址,所以就是false

public static void main(String[] args) {

char[] ch = new char[]{'s', 't', 'a', 'y'};
String s1 = new String(ch);
String s2 = "stay";
System.out.println(s1 == s2);//false

}
//常量池里面没有stay,所以s2就会创建一个对象,所以s1和s2里面存储不同的地址,所以就是false
复制代码
intern(手动入池)
public static void main(String[] args) {

char[] ch = new char[]{'s', 't', 'a', 'y'};
String s1 = new String(ch);
s1.intern();
String s2 = "stay";
System.out.println(s1 == s2);//false

}
////添加一个intern,就将s1指向的对象/字符串内容放进了常量池,所以接下来s2就可以在常量池里面找到stay,所以s1==s2成立
复制代码
请解释一下String两种对象实例化的区别
前提:常量池中没有hello

1.String str="hello";

思路:创建一个对象,就是常量池对象hello

只会开辟一块内存空间,保存在字符串常量池中,然后str共享常量池的String对象

2.String str=new String ("hello");

思路:创建两个对象:常量池的对象hello String对象本身

会开辟两块堆内存空间,字符串"hello"保存在字符串常量池中,然后用常量池中的String对象给新开辟 的String对象赋值。

3.String str = new String(new char[]{'h', 'e', 'l', 'l', 'o'})

思路:创建3个对象

现在堆上创建一个String对象,然后利用copyof将重新开辟数组空间,将参数字符串数组中内容拷贝到String对象中

字符串的不可变性
为什么字符串不可变?

image-20220531231131444

是因为String里面的value数组是private的,外面是访问不到的,所以字符串不能被修改

public static void main(String[] args) {

String str = "stay hungry";
str = "haha";
System.out.println(str);

}
//haha
复制代码
==注意==

这里的字符串stay hungry并没有被改变,只是s1这个字符串变量的指向发生了变化

计算机的内部会再产生一个字符串对象,给这个对象赋值为"hello",然后字符串变量s1指向这里的新产生的对象,所以打印出来的是haha

stringBuilder 和 StringBuffer
public static void main(String[] args) {

String s = "hello";
s += " world";
System.out.println(s);

}
//也就是在world后面追加一个world
复制代码
上面的追加代码的底层是什么样子的?

public static void main(String[] args) {

StringBuilder stringBuilder = new StringBuilder();//首先会创建一个对象
stringBuilder.append("hello");//append的意思是追加
stringBuilder.append(" world");
  String s = stringBuilder.toString();
   System.out.println(s);

}
//输出结果是hello world
复制代码
也就是说,每想要追加,就要创建一次对象

因此就要防止写出下面的代码:

public static void main(String[] args) {

String s = "hello";
for (int i = 0; i < 5; i++) {
    s += "haha";
}
System.out.println(s);
//追加了5次,也就是说,创建了5个临时的对象,占用空间,一定不要这么写

复制代码
StringBuilder下面还有很多的很好用的方法

//字符串的逆置,直接调用StringBuilder下面的reverse方法
public static void main21(String[] args) {

StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("hello");
stringBuilder.append(" world");
System.out.println(stringBuilder);
stringBuilder.reverse();
System.out.println(stringBuilder);

}
复制代码
StringBuilder和StringBuffer的区别
image-20220602200800565

==小总结==

String StringBuilder StringBuffer三者的区别
1.String的内容不能被修改,但是StringBuilder和StringBuffer的内容可以被修改

2.StringBuilder和StringBuffer的功能几乎是一样的

3.StringBuffer采用同步处理,属于线程安全操作,但是StringBuilder没有采用同步处理,属于线程不安全操作

2、判断下面的一共创建了几个对象 (前提不考虑常量池之前是否存在)

String str = new String("ab");
一共会创建两个对象,分别是“ab”常量池和 String对象

String str = new String("a") + new String("b");
首先会创建“a”和 "b"两个常量池对象,其次会创建两个String对象,由于要进行拼接,所以会创建一个StringBuilder对象,最后还会调用一个toString方法,再创建一个对象,所以一共有6个对象

image-20220602202525490

目录
相关文章
|
11天前
|
安全 程序员 C++
C++ --> string类的使用(详细介绍)
C++ --> string类的使用(详细介绍)
26 5
|
11天前
|
存储 编译器 C语言
C++ --> string类模拟实现(附源码)
C++ --> string类模拟实现(附源码)
35 4
|
11天前
|
安全 Java
12 Java常用类(二)(String类+时间类+BigDecimal类等等)
12 Java常用类(二)(String类+时间类+BigDecimal类等等)
23 2
|
6天前
|
编译器 C语言 C++
【C++】模拟实现string类
【C++】模拟实现string类
|
6天前
|
存储 算法 C语言
【C++】认识使用string类
【C++】认识使用string类
|
1月前
|
编译器 C++
【C++】string类的使用④(字符串操作String operations )
这篇博客探讨了C++ STL中`std::string`的几个关键操作,如`c_str()`和`data()`,它们分别返回指向字符串的const char*指针,前者保证以&#39;\0&#39;结尾,后者不保证。`get_allocator()`返回内存分配器,通常不直接使用。`copy()`函数用于将字符串部分复制到字符数组,不添加&#39;\0&#39;。`find()`和`rfind()`用于向前和向后搜索子串或字符。`npos`是string类中的一个常量,表示找不到匹配项时的返回值。博客通过实例展示了这些函数的用法。
|
1月前
|
存储 C++
【C++】string类的使用③(非成员函数重载Non-member function overloads)
这篇文章探讨了C++中`std::string`的`replace`和`swap`函数以及非成员函数重载。`replace`提供了多种方式替换字符串中的部分内容,包括使用字符串、子串、字符、字符数组和填充字符。`swap`函数用于交换两个`string`对象的内容,成员函数版本效率更高。非成员函数重载包括`operator+`实现字符串连接,关系运算符(如`==`, `&lt;`等)用于比较字符串,以及`swap`非成员函数。此外,还介绍了`getline`函数,用于按指定分隔符从输入流中读取字符串。文章强调了非成员函数在特定情况下的作用,并给出了多个示例代码。
|
1月前
|
安全 Java 索引
带你快速掌握Java中的String类和StringBuffer类(详解常用方法 | 区别 )
带你快速掌握Java中的String类和StringBuffer类(详解常用方法 | 区别 )
|
1月前
|
存储
数据存储之数组的特点,长度固定,适应变化需求,集合类特点是空间可变,ArrayList泛型,ArrayList<String> array = new ArrayList<String>()
数据存储之数组的特点,长度固定,适应变化需求,集合类特点是空间可变,ArrayList泛型,ArrayList<String> array = new ArrayList<String>()
|
1月前
|
C++
【C++】string类的使用④(常量成员Member constants)
C++ `std::string` 的 `find_first_of`, `find_last_of`, `find_first_not_of`, `find_last_not_of` 函数分别用于从不同方向查找目标字符或子串。它们都返回匹配位置,未找到则返回 `npos`。`substr` 用于提取子字符串,`compare` 则提供更灵活的字符串比较。`npos` 是一个表示最大值的常量,用于标记未找到匹配的情况。示例代码展示了这些函数的实际应用,如替换元音、分割路径、查找非字母字符等。