java中string不可变指对象内容不可修改,而非变量不能重新赋值;其设计支撑常量池复用、线程安全、哈希值缓存及系统安全性,频繁拼接应使用stringbuilder或stringbuffer优化。

Java 中 String 的不可变性不是“不能改变变量”,而是“不能改变对象内容”。很多面试混淆都源于没分清 引用 和 对象、字面量 和 new 创建的对象、== 和 .equals() 这三组关键区别。只要抓住这三点,大部分概念题都能稳住不掉坑。
别把“s = s + 'a'”当成修改原对象
这是最典型的误解。代码看似在“改”字符串,实际每次拼接都生成新对象,原对象留在内存里(除非被 GC 回收):
- 错误理解:String s = "hello"; s += " world"; → 原来那个 "hello" 被改成了 "hello world"
- 正确理解:s += " world" 等价于 s = new StringBuilder().append(s).append(" world").toString(); 原 "hello" 对象未动,s 只是换了个新地址指向
- 验证方式:用 == 比较拼接前后 s 和原始引用,结果一定是 false
区分字面量和 new 创建的 String 对象
常量池只对字符串字面量(如 "abc")自动生效,new String("abc") 一定在堆上新建对象,哪怕内容相同也不进池(除非手动调 intern()):
- String a = "abc"; String b = "abc"; → a == b 为 true(共享常量池中同一对象)
- String c = new String("abc"); String d = new String("abc"); → c == d 为 false(两个独立堆对象)
- c.intern() == a 为 true(intern() 强制入池并返回池中引用)
== 和 .equals() 的本质差异必须讲透
面试官爱问 “为什么 String 重写了 equals()?”,答案不能只说“比较内容”,要落到设计动机:
- ==:永远比较内存地址,适用于判断是否为同一对象(比如检查缓存命中、单例判等)
- .equals():String 重写后逐字符比内容,因为业务上我们关心的是“值相等”,不是“是不是同一个对象”
- 延伸点:String 的 hashCode() 也基于内容计算且缓存,所以能安全作为 HashMap 键——这点直接关联不可变性的优势
别拿 StringBuffer/Builder 反推 String 可变
有人看到 StringBuilder.append() 能改内容,就反推 “String 其实也能改,只是没提供方法”。这是逻辑倒置:
- StringBuilder 是专为可变场景设计的工具类,它的内部 char[] 没有 final,也没有私有封装限制
- String 的不可变是主动设计选择,不是功能缺失;它牺牲了拼接性能,换来了线程安全、常量池、哈希缓存等关键能力
- 面试时若被问“怎么高效拼接”,答“用 StringBuilder”即可;但若被问“为什么不用 String 拼接”,就要答出 GC 压力、内存浪费、O(n²) 时间复杂度这些具体代价
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











