String的不可变性带来三大优势:一是字符串常量池复用,减少内存占用;二是天然线程安全,无需同步即可共享;三是哈希码缓存提升性能。

String 的不可变性直接决定了它在内存和并发场景中的行为——不是靠额外加锁或缓存策略实现的优化,而是由设计本身带来的天然优势。
字符串常量池复用,减少内存占用
Java 中字面量创建的 String(如 "hello")会优先从字符串常量池查找。由于不可变,相同内容的字符串可安全共享同一对象,避免重复分配堆内存。
- 例如:String a = "abc"; String b = "abc"; → a == b 为 true,指向常量池中同一个实例
- 若 String 可变,修改 a 就会影响 b,池化机制无法成立
- 注意:new String("abc") 总是新建堆对象,不进池(除非显式调用 intern())
无需同步即可安全共享,简化多线程编程
不可变对象天然是线程安全的:没有可变状态,就没有竞态条件。多个线程读取、传递、作为 key 使用 String 都不需要加锁或防御性拷贝。
- HashMap 的 key 常用 String,因为它的 hash 值在构造时就已确定且永不改变,保证散列稳定性
- 日志系统中传递 String 参数,不用担心其他线程中途篡改内容
- 对比:StringBuilder 是可变的,多线程共用必须手动同步,否则结果不可预测
哈希码缓存提升性能,避免重复计算
String 内部缓存了 hash 字段(首次调用 hashCode() 时计算并保存)。因内容不可变,该值永久有效。
- 频繁用于哈希集合(HashSet、HashMap)时,每次查找/插入都省去重新计算 hash 的开销
- 若 String 可变,hash 值需动态更新,不仅慢,还会导致对象在哈希表中“丢失”(位置错乱)
- 这个缓存是透明的,开发者无需干预,但理解它有助于解释为什么 String 的 hashCode 效率高
注意不可变性的边界:引用 vs 内容
不可变指的是 String 对象封装的字符序列不可更改,不是指引用不能重新赋值。
- String s = "a"; s = "b"; —— 这里不是修改原对象,而是让 s 指向新对象,“a” 仍存在(可能被回收)
- 所有看似“修改”的方法(如 substring、toUpperCase)都返回新 String,原对象不变
- 真正要避免内存浪费的是过度拼接(如循环中用 +),应改用 StringBuilder
















