Java 字符串不可变性
什么是字符串的不可变性?
在Java中,String类是一个特殊的类,它具有一个重要的 特性:不可变性(Immutability)。这意味着一旦创建了String对象,就无法更改其内容。任何看似修改String的操作实际上都是创建了一个全新的String对象,而原始的String对象保持不变。
关键概念
不可变对象:创建后其状态(即存储的数据)不能被修改的对象。
字符串不可变性的原理
Java中的String类在内部是这样实现的:
public final class String {
private final char[] value;
// 其他字段和方法
}
注意以上代码中两个关键字:
final
类:String类被声明为final,这意味着它不能被继承private final char[]
:字符数组被声明为private和final,这确保了数组引用不能被修改
这样的设计确保了String对象一旦被创建,其内容就不能被更改。
字符串不可变性的验证
让我们通过一些示例来验证字符串的不可变性:
String s1 = "Hello";
String s2 = s1;
System.out.println("s1: " + s1); // 输出: s1: Hello
System.out.println("s2: " + s2); // 输出: s2: Hello
System.out.println("s1 == s2: " + (s1 == s2)); // 输出: s1 == s2: true
s1 = s1 + " World";
System.out.println("修改后的 s1: " + s1); // 输出: 修改后的 s1: Hello World
System.out.println("s2: " + s2); // 输出: s2: Hello
System.out.println("s1 == s2: " + (s1 == s2)); // 输出: s1 == s2: false
在上面的示例中,当我们执行 s1 = s1 + " World"
时,实际上发生了以下步骤:
- 创建了一个新的String对象,内容为 "Hello World"
- 将s1引用指向这个新对象
- 原始的 "Hello" 字符串对象仍然存在,s2仍然指向它
这 就是为什么修改s1后,s1和s2不再是同一个对象(s1 == s2为false)。
字符串池(String Pool)
Java的字符串不可变性与字符串池(String Pool)密切相关。字符串池是Java堆内存中的一个特殊区域,用于存储字符串常量。
String str1 = "Java"; // 创建一个字符串 "Java" 并放入字符串池
String str2 = "Java"; // 从字符串池中获取已有的 "Java"
String str3 = new String("Java"); // 强制在堆中创建新对象
System.out.println(str1 == str2); // 输出: true(相同引用)
System.out.println(str1 == str3); // 输出: false(不同引用)
System.out.println(str1.equals(str3)); // 输出: true(内容相等)
字符串池的工作原理可以用下面的图表来说明: