java string不可变性指逻辑内容不可改,修改操作均返回新对象;jdk 9通过byte[]+coder字段实现紧凑字符串,在保持不可变契约前提下,使ascii字符串内存减半。

Java 中 String 的不可变性,不是指“完全锁死内存”,而是指逻辑上内容不可更改:任何修改操作(如 replace、substring、toUpperCase)都返回新对象,原对象保持原样。JDK 9 的字节数组优化(byte[] value + coder 字段)在不破坏这一契约的前提下,显著节省了内存。
不可变性的三层保障机制
String 的不可变不是靠单个关键字实现的,而是一套协同设计:
- final 类:无法被继承,杜绝子类绕过封装添加修改方法;
-
private final 字段:内部存储数组(JDK 8 是
char[],JDK 9+ 是byte[])既不可被外部访问,引用也不可重定向; - 无写入接口:所有 public 方法都不修改自身,只构造并返回新 String;构造器还做防御性拷贝,避免传入数组被外部篡改。
JDK 9 的 byte[] 优化不是为了“可变”,而是为了“更省”
这个改动来自 JEP 254(Compact Strings),核心目标是降低内存占用,尤其对纯 ASCII/Latin-1 字符串:
- JDK 8:统一用
char[],每个字符固定占 2 字节(UTF-16),哪怕只是字母'a'也浪费 1 字节; - JDK 9+:
byte[] value+byte coder(0=Latin-1,1=UTF-16); - 效果:英文字符串内存减半;含中文时自动升为 UTF-16 编码,兼容性不变;
length()仍返回字符数(不是字节数),业务代码完全无感。
不可变性与底层存储是正交的两个维度
有人误以为“换成 byte[] 就可能被改内容”,其实不然:
- final 修饰的是
byte[]引用,和之前修饰char[]效果一致; - private + 无 setter + 构造时拷贝 → 外部根本拿不到、也改不了这个数组;
- 即使反射强行修改内部
byte[],属于破坏 JVM 合约的非常规行为,不在 Java 语言语义保证范围内。
对日常开发的实际影响
理解这两点,能帮你写出更健壮、高效的代码:
- 拼接大量字符串时,别在循环里用
+(每次生成新对象),改用StringBuilder; - 比较内容必须用
.equals(),==只比引用,常量池中相同字面量才可能相等; - 作为
HashMap的 key 安全可靠,因为不可变 →hashCode可缓存且永不失效; - 多线程间共享字符串无需同步,天然线程安全。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











