Java中String不可变性由private、final和无写方法三者协同实现:private阻断外部访问,final锁定引用,无写方法确保不修改内容,缺一不可。

Java 中 String 的不可变性,不能只看 private final char[] value 这一行代码。它表面是“私有+最终”,但真正起作用的是三者协同:私有(private)切断外部访问路径,final(final)锁死引用指向,再加上无任何写方法——三者缺一不可。
私有(private)不是摆设,而是第一道防线
String 内部的 value 字段被声明为 private final,意味着:
- 外部类连字段名都看不到,更别说通过
str.value[0] = 'x'直接改内容; - 没有 public 或 protected 的 getter 返回该数组的引用(不像某些自定义类会暴露
getArray()); - 子类也无法继承并绕过封装——因为 String 本身是
final class,根本不能被继承。
为什么仅靠 final char[] 不足以保证内容不变?
很多人误以为 final 数组 = 数组内容不可变。这是常见误区。final 只约束引用不可重定向,不约束数组元素可修改:
例如这段代码完全合法:
final char[] arr = {'a', 'b'};<br>arr[0] = 'z'; // ✅ 允许!final 不阻止改元素<br>// arr = new char[3]; // ❌ 不允许!引用不能变
所以,如果 String 把 value 设为 public final,哪怕没提供 set 方法,别人也能拿到引用、直接改数组内容——不可变性就彻底崩塌了。private 正是堵死这个漏洞的关键设计。
构造时还做了防御性拷贝,防内部篡改
String 构造器对传入的字符数组不是直接赋值,而是主动拷贝一份:
public String(char[] value) {<br> this.value = Arrays.copyOf(value, value.length); // 拷贝新数组<br>}
这样即使调用方后续修改了原始数组(比如 value[0] = 'X'),也不会影响已创建的 String 对象。这叫防御性拷贝,是从源头上隔绝外部干扰。
没有写方法,才是“不可变”的最终体现
String 类里所有看似“修改”的方法,如 replace()、substring()、toUpperCase(),全部返回新 String 对象,从不改动自身 value:
- 没有
setCharAt(int, char); - 没有
append()、insert()、delete(); - 甚至
concat()也是新建数组、拷贝两段内容、再 new String。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











