Java String 类详解
一、String 类概述
- 不可变性:
String
类在 Java 中是不可变的,即一旦创建,其内容不能被修改。这种设计保证了线程安全,并且可以被多个线程共享。 - 存储方式:在 JDK 8 及之前,
String
内部使用 char[]
存储字符数据;从 JDK 9 开始,改为使用 byte[]
加上编码标记,以节约空间。 - 实现接口:
String
类实现了 Serializable
、Comparable<String>
和 CharSequence
接口,支持序列化、比较和字符序列操作。
二、字符串的创建
- 字面量创建:
String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2); // true,指向常量池中的同一个对象
- 使用
new
关键字创建:
String str3 = new String("Hello");
String str4 = new String("Hello");
System.out.println(str3 == str4); // false,str3 和 str4 是堆中的不同对象
System.out.println(str1.equals(str3)); // true,内容相同
- 使用字符数组或字节数组创建:
char[] charArray = {'H', 'e', 'l', 'l', 'o'};
String str5 = new String(charArray);
byte[] byteArray = {72, 101, 108, 108, 111}; // ASCII 码对应 'H', 'e', 'l', 'l', 'o'
String str6 = new String(byteArray);
三、String 类的常用方法
- 字符串比较:
equals(Object obj)
:比较内容是否相同。equalsIgnoreCase(String str)
:忽略大小写比较内容。compareTo(String str)
:按字典顺序比较字符串。
- 字符串获取:
length()
:返回字符串长度。charAt(int index)
:返回指定索引处的字符。
- 字符串截取:
substring(int beginIndex)
:从 beginIndex
开始截取到末尾。substring(int beginIndex, int endIndex)
:截取从 beginIndex
到 endIndex - 1
的子字符串。
- 字符串查找:
indexOf(String str)
:返回子字符串首次出现的索引。lastIndexOf(String str)
:返回子字符串最后一次出现的索引。
- 字符串转换:
toLowerCase()
:转换为小写。toUpperCase()
:转换为大写。trim()
:去除首尾空格。
- 字符串替换:
replace(char oldChar, char newChar)
:替换所有匹配的字符。replace(CharSequence target, CharSequence replacement)
:替换所有匹配的子字符串。
- 字符串分割:
split(String regex)
:根据正则表达式拆分字符串。
四、字符串常量池
- 作用:为了提高性能和减少内存开销,Java 引入了字符串常量池。当使用字面量创建字符串时,如果常量池中已经存在相同内容的字符串,则直接返回常量池中的引用;否则,在常量池中创建一个新的字符串对象。
- 示例:
String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2); // true,指向常量池中的同一个对象
String str3 = new String("Hello");
System.out.println(str1 == str3); // false,str3 是堆中的新对象
System.out.println(str1.equals(str3)); // true,内容相同
五、字符串拼接
String str1 = "Hello";
String str2 = "World";
String str3 = str1 + " " + str2; // "Hello World"
- 编译器会优化为
StringBuilder
的 append
操作,但在循环中频繁拼接时性能较差。 - 使用
concat
方法:
String str4 = str1.concat(" ").concat(str2); // "Hello World"
StringBuilder sb = new StringBuilder();
sb.append(str1).append(" ").append(str2);
String result = sb.toString(); // "Hello World"
六、String、StringBuilder 和 StringBuffer 的区别
- String:不可变,线程安全,适合不需要修改的字符串。
- StringBuilder:可变,非线程安全,性能高,适合单线程环境下的字符串操作。
- StringBuffer:可变,线程安全,性能稍低,适合多线程环境下的字符串操作。
七、注意事项
- 字符串判空:
String str = null;
if (str == null || str.isEmpty()) { // 正确写法
System.out.println("String is null or empty");
}
- 字符串分割:
- 特殊字符(如
.
、*
、+
)需要转义:
java String[] parts = "a.b.c".split("\\."); // ["a", "b", "c"]
- 性能优化:
- 避免在循环中使用
+
拼接字符串,应使用 StringBuilder
。 - 使用
intern()
方法将字符串放入常量池(需谨慎使用,避免内存泄漏)。