题目
Java中String类的不可变性
信息
- 类型:问答
- 难度:⭐
考点
String不可变性,字符串池,字符串操作
快速回答
String对象在Java中是不可变的,主要特点包括:
- 一旦创建,内容不可修改
- 字符串拼接等操作会创建新对象
- 使用字符串池(String Pool)优化内存
- 线程安全,无需额外同步
1. 不可变性原理
String类使用final char[] value存储字符数据,且不提供修改数组内容的方法。关键源码:
public final class String {
private final char value[];
// 无修改value数组的public方法
}任何看似修改的操作(如concat()、replace())都返回新创建的String对象,原对象不变。
2. 代码示例
String s1 = "hello";
String s2 = s1.concat(" world"); // 创建新对象
System.out.println(s1); // 输出:hello(未改变)
System.out.println(s2); // 输出:hello world
s1.toUpperCase(); // 返回新对象,但未接收
System.out.println(s1); // 仍输出:hello3. 字符串池(String Pool)机制
- 使用字面量(如
"abc")创建字符串时,JVM会检查字符串池是否存在相同内容 - 若存在则直接返回池中引用,否则创建新对象并加入池中
new String("abc")会强制在堆中创建新对象(不推荐)
String a = "cat"; // 放入字符串池
String b = "cat"; // 复用池中对象
String c = new String("cat"); // 在堆中新建对象
System.out.println(a == b); // true(相同引用)
System.out.println(a == c); // false(不同对象)4. 最佳实践
- 字符串拼接:优先使用
StringBuilder(非线程安全)或StringBuffer(线程安全)避免频繁创建对象 - 比较相等:始终用
equals()而非==(==比较引用地址) - 重用对象:尽量使用字面量声明字符串
5. 常见错误
- 在循环中拼接字符串:
// 错误示例:每次循环创建新String对象 String result = ""; for (int i = 0; i < 1000; i++) { result += i; // 性能极差! } // 正确做法:使用StringBuilder StringBuilder sb = new StringBuilder(); for (int i = 0; i < 1000; i++) { sb.append(i); } String result = sb.toString(); - 误用
==比较内容:String s1 = new String("java"); String s2 = new String("java"); System.out.println(s1 == s2); // false!应使用s1.equals(s2)
6. 扩展知识
- 内存优化:不可性使字符串池成为可能,减少重复对象
- 安全性:广泛用于网络连接、文件路径等场景,防止被篡改
- HashCode缓存:String重写
hashCode(),首次计算后缓存结果(因内容不变)