七、java中的字符串(String、StringBuilder、StringJoiner)
字符串
具体信息请查看 API 帮助文档
七、字符串
1.String类
? String 类代表字符串,Java 程序中的所有字符串文字(例如“abc”)都被实现为此类的实例。Java 程序中所有的双引号字符串,都是 String 类的对象。
String 类在 java.lang 包下,所以使用的时候不需要导包!
1.1 特点
-
不可变性:String对象在创建后不可被修改。
这意味着一旦一个String对象被赋值,它的值就不能再被改变。 如果我们对一个String对象执行任何的修改操作,实际上是创建了一个全新的String对象来存储修改后的值。 这样的设计是为了提高性能和安全性,因为不可变的String对象可以在多线程环境下共享而不会出现意外的修改。
-
字符串字面量:Java提供了字符串字面量的方式来表示String对象。
字符串字面量是用双引号括起来的字符序列,例如:"Hello"。 字符串字面量在编译时就会自动优化为String对象,可以直接使用,而不需要显式的调用构造函数。 此外,多个字符串字面量可以通过"+"运算符连接起来,形成一个新的String对象。
-
字符编码:String类使用UTF-16编码(Unicode字符集的一种)来表示字符串,每个字符占用16位。
我们可以通过`getBytes()`方法将字符串转换为指定的字符编码(如UTF-8)
-
字符串池:为了提高性能和节省内存,Java使用了字符串池的概念。
字符串池是一个字符串缓存区域,存储着已经创建的字符串对象。 当我们创建新的字符串对象时,首先会检查字符串池中是否已存在相同内容的字符串。 如果存在,则返回池中的引用,而不会创建新的对象。 这样可以减少内存消耗和垃圾回收的开销,提高程序的性能。
-
运算符重载:String类重载了加号"+"运算符,可以用于连接多个字符串。
这个特性使得字符串拼接变得简洁和直观,例如:"Hello" + "World"将会得到一个新的字符串"HelloWorld"。
-
性能优化:由于String对象的不可变性,它们在多线程环境下是安全的并且可以被共享。
这样可以避免许多并发问题,并提高程序的性能。
-
字符串拼接性能优化:在需要频繁拼接字符串的场景下,使用
StringBuilder
类或StringBuffer
类可以提升性能。`StringBuilder`和`StringBuffer`是可变的字符序列,可以在原地修改字符串,而不需要创建新的对象。 `StringBuilder`是线程不安全的,适用于单线程环境。 StringBuffer`是线程安全的,适用于多线程环境。
1.2 构造方法
- 常用的构造方法
方法名 | 说明 |
---|---|
public String() | 创建一个空白字符串对象,不含有任何内容 |
public String(char[] chs) | 根据字符数组的内容,来创建字符串对象 |
public String(byte[] bys) | 根据字节数组的内容,来创建字符串对象 |
String s = “abc”; | 直接赋值的方式创建字符串对象,内容就是abc |
- 示例代码
public class StringDemo01 {
public static void main(String[] args) {
//public String():创建一个空白字符串对象,不含有任何内容
String s1 = new String();
System.out.println("s1:" + s1);
//public String(char[] chs):根据字符数组的内容,来创建字符串对象
char[] chs = {'a', 'b', 'c'};
String s2 = new String(chs);
System.out.println("s2:" + s2);
//public String(byte[] bys):根据字节数组的内容,来创建字符串对象
byte[] bys = {97, 98, 99};
String s3 = new String(bys);
System.out.println("s3:" + s3);
//String s = “abc”; 直接赋值的方式创建字符串对象,内容就是abc
String s4 = "abc";
System.out.println("s4:" + s4);
}
}
1.3 成员方法
方法名称 | 描述 |
---|---|
char charAt(int index) | 返回指定索引处的 char 值。 |
int compareTo(String anotherString) | 按字典顺序比较两个字符串。 |
int compareToIgnoreCase(String str) | 按字典顺序比较两个字符串,不考虑大小写。 |
boolean equals(Object anObject) | 将此字符串与指定的对象比较。 |
boolean equalsIgnoreCase(String anotherString) | 将此 String 与另一个 String 比较,不考虑大小写。 |
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) | 将字符从此字符串复制到目标字符数组。 |
int length() | 返回此字符串的长度。 |
String replace(char oldChar, char newChar) | 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。 |
String substring(int beginIndex) | 返回一个新的字符串,它是此字符串的一个子字符串。 |
String substring(int beginIndex, int endIndex) | 返回一个新字符串,它是此字符串的一个子字符串。 |
String toString() | 返回此对象本身(它已经是一个字符串!)。 |
这些方法均属于String
类中的实例方法,用于操作字符串。具体来说:
- `charAt(int index)`方法用于获取指定索引位置上的字符。
- `compareTo(String anotherString)`方法用于比较两个字符串,按字典顺序比较。
- `compareToIgnoreCase(String str)`方法与`compareTo`方法类似,但不考虑大小写。
- `equals(Object anObject)`方法用于判断当前字符串是否与指定的对象相等。
- `equalsIgnoreCase(String anotherString)`方法与`equals`方法类似,但不考虑大小写。
- `getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)`方法用于将当前字符串中指定范围的字符复制到目标字符数组中。
- `length()`方法用于获取当前字符串的长度。
- `replace(char oldChar, char newChar)`方法用于替换当前字符串中指定字符的值。
- `substring(int beginIndex)`方法用于获取当前字符串中子串,从指定索引位置开始到结尾。
- `substring(int beginIndex, int endIndex)`方法用于获取当前字符串中子串,从指定开始索引位置到指定结束索引位置的子串。
- `toString()`方法用于将当前对象转换为字符串,该方法的实现返回当前对象本身,因为`String`本身就是一个字符串。
1.4 创建对象方式的区别
-
通过构造方法创建
? 通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同
-
直接赋值方式创建
? 以“ ”方式给出的字符串,只要字符串相同,JVM 都只会建立一个 String 对象,并在字符串池中维护
1.5 字符串的比较
1.5.1 ==号的作用
- 比较基本数据类型:比较的是具体的值
- 比较引用数据类型:比较的是对象地址值
1.5.2 equals方法
-
方法介绍
public boolean equals(String s) 比较两个字符串内容是否相同、区分大小写
示例代码:
public class StringDemo02 { public static void main(String[] args) { //构造方法的方式得到对象 char[] chs = {'a', 'b', 'c'}; String s1 = new String(chs); String s2 = new String(chs); //直接赋值的方式得到对象 String s3 = "abc"; String s4 = "abc"; //比较字符串对象地址是否相同 System.out.println(s1 == s2);//false System.out.println(s1 == s3);//false System.out.println(s3 == s4);//true System.out.println("--------"); //比较字符串内容是否相同 System.out.println(s1.equals(s2));//true System.out.println(s1.equals(s3));//true System.out.println(s3.equals(s4));//true } }
2. StringBuilder
2.1 构造方法
- 空参构造
StringBuilder stringBuilder=new StringBuilder();
- 带参构造
StringBuilder stringBuilder=new StringBuilder("aaaa");
2.2 成员方法
-
append() :添加StringBuilder的内容
-
reverse() :反转StringBuilder的内容
-
length() :获取StringBuilder的长度
-
toString(): 转换成字符串
(因为StringBuilder是一个长度可变容器,需要将最后结果转换成字符串,字符串长度固定,不可变)
注意:StringBuilder打印的不是地址值而是属性值,因为其是java已经写好的类,在底层对其进行了一些处理
StringBuilder 可以看成是一个容器,创建之后里面的内容是可变的。
例如:
public class StringBuilderDemo3 {
public static void main(String[] args) {
//1.创建对象
StringBuilder sb = new StringBuilder("abc");
//2.添加元素
/*sb.append(1);
sb.append(2.3);
sb.append(true);*/
//反转
sb.reverse();
//获取长度
int len = sb.length();
System.out.println(len);
System.out.println(sb);
}
}
3. StringJoiner
3.1 构造方法
-
StringJoiner stringJoiner=new StringJoiner(“delimiter”);
delimiter:间隔符号
-
StringJoiner stringJoiner=new StringJoiner(“delimiter”,“prefix”,“suffix”); 、
delimiter:间隔符号;prefix:开始符号;suffix:结束符号;
3.2 成员方法
-
add() 添加StringJoiner的内容
-
length() 获取StringJoiner的长度
注意:长度为所有的字符的长度,包括间隔符号,开始符号,结束符号
-
toString() 转换成字符串
(因为StringJoiner是一个长度可变容器,需要将最后结果转换成字符串,串长度固定,不可变)
注意:StringJoiner打印的不是地址值而是属性值,因为其是java已经写好的类,在底层对其进行了一些处理
例如:
//1.创建一个对象,并指定中间的间隔符号
StringJoiner sj = new StringJoiner("---");
//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
//3.打印结果
System.out.println(sj);//aaa---bbb---ccc
//1.创建对象
StringJoiner sj = new StringJoiner(", ","[","]");
//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
int len = sj.length();
System.out.println(len);//15
//3.打印
System.out.println(sj);//[aaa, bbb, ccc]
String str = sj.toString();
System.out.println(str);//[aaa, bbb, ccc]
4. 字符串原理
-
字符串存储的内存原理
- 直接赋值会复用字符串串池中的
- new出来的不会复用,而是开辟一个新的空间
-
==号比较的到底是什么?
如果比较的是基本数据类型:比的是具体的数值是否相等。
如果比较的是引用数据类型:比的是地址值是否相等。
-
字符串拼接的底层原理
-
字符串拼接包含变量:
当字符串拼接包含变量时,使用
+
运算符进行拼接,底层会使用StringBuilder
类来执行拼接操作。StringBuilder
类在拼接变量时,会将变量的值转换为字符串并追加到当前的StringBuilder
对象中。例如:
String name = "Alice"; int age = 25; String message = "My name is " + name + " and I am " + age + " years old.";
这段代码编译后的实际执行是:
StringBuilder sb = new StringBuilder(); sb.append("My name is "); sb.append(name); sb.append(" and I am "); sb.append(age); sb.append(" years old."); String message = sb.toString();
可以看到,变量名和值都被转换为字符串,并追加到
StringBuilder
对象中,然后通过toString()
方法得到最终的拼接结果。 -
字符串拼接不包含变量:
当字符串拼接不包含变量时,使用
+
运算符进行拼接,底层会直接进行字符串的连接操作。由于没有变量,编译器可以在编译时确定整个拼接结果。
例如:
String str1 = "Hello"; String str2 = "World"; String result = str1 + ", " + str2;
这段代码编译后的实际执行是:
String result = "Hello, " + "World";
可以看到,编译器直接将不同字符串字面量连接在一起,形成最终的拼接结果。
-
-
StringBuilder提高效率原理
-
可变性:
StringBuilder
是可变的字符序列,可以在原地修改字符串内容。相比于String
类的不可变性,使用StringBuilder
可以避免频繁创建新的字符串对象。 -
内部缓冲区:
StringBuilder
内部使用一个可扩展的字符数组作为缓冲区,用于存储字符串的内容。在进行字符串拼接时,StringBuilder
会将新的字符追加到缓冲区中。 -
避免创建中间对象:当使用
+
运算符或concat()
方法进行字符串拼接时,每次拼接都会创建一个新的字符串对象。而StringBuilder
则避免了这一点,在进行拼接操作时直接在缓冲区中修改字符串内容,避免了频繁创建新的字符串对象。需要注意的是,`StringBuilder`是非线程安全的。 如果在多线程环境下进行字符串操作,应该使用线程安全的`StringBuffer`类来替代`StringBuilder`。 `StringBuffer`的使用方式和`StringBuilder`类似,但具备线程安全的特性。
-
具体信息请查看 API 帮助文档
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!