String不可变性是设计选择而非缺陷,体现为内容与长度创建后不可修改,所有“修改”操作均返回新对象;其由final类、private final value数组及无修改方法共同保障,带来线程安全、哈希稳定、常量池复用和安全性四大优势。

String 不可变性是设计选择,不是缺陷
String 的不可变性体现在:一旦创建,其内容(字符序列)和长度就无法被修改。所有看似“修改”的操作,比如 concat、replace、substring、甚至用 + 拼接,都只是返回一个新对象,原对象毫发无损。这是因为 String 内部的 value 数组被声明为 private final,且类本身是 final,外部既不能改引用,也不能改内容,更无法继承重写行为。
StringBuilder 和 StringBuffer 都是可变的,但安全机制不同
两者都继承自 AbstractStringBuilder,底层使用非 final 的 char[] 或 byte[] 存储数据,并提供 append、insert、delete 等直接修改内部数组的方法。它们不会为每次拼接都新建对象,只在容量不足时扩容数组——这正是解决 String 频繁拼接性能问题的核心设计。
- StringBuffer 的每个关键方法(如 append)都加了 synchronized,保证多线程并发修改时数据一致,但同步锁带来开销
- StringBuilder 完全不加锁,方法调用无额外同步成本,因此单线程下性能明显更高
不可变性带来的实际影响,直接决定使用场景
String 的不可变性不是为了“限制你”,而是服务于多个关键需求:
- 线程安全:多个线程同时读取同一个 String,完全不用担心值被意外改写
- 哈希稳定:作为 HashMap 的 key 时,hashCode 只算一次、缓存起来,后续查找不会因内容变化而失效
- 字符串常量池复用:字面量 "abc" 多次出现,JVM 只在常量池存一份,节省内存
- 安全性:用作文件路径、SQL 片段、URL 等敏感字符串时,避免被中途篡改
而 StringBuilder 和 StringBuffer 不具备这些优势——它们的对象不能进常量池,hash 值不缓存,也不适合当 Map 的 key;但它们专为“要反复改”的场景而生,比如日志拼接、XML 构建、循环内累积字符串。
立即学习“Java免费学习笔记(深入)”;
选哪个?看三点:是否要改、是否多线程、是否做 key
一句话判断:
- 字符串确定不变 → 用 String(例如配置项、协议头、枚举名)
- 单线程下频繁拼接或修改 → 用 StringBuilder(95% 的日常拼接场景)
- 多线程共享同一对象并需并发修改 → 用 StringBuffer(极少,通常应优先考虑重构避免共享)
混淆三者,往往不是语法问题,而是没想清楚“这个字符串在程序里到底扮演什么角色”。


















