Java String核心在于不可变性、常量池机制和对象创建方式:底层数组final修饰、修改方法均新建对象;字面量走常量池,new创建在堆;intern()返回池中引用而非放入池。

准备 Java String 面试题,关键不是背答案,而是理清三条主线:不可变性、常量池机制、对象创建方式。只要这三点吃透,90% 的高频题都能自己推导出来。
紧扣不可变性,解释所有“为什么”
String 不可变,不是一句结论,而是有具体体现的:
- 底层 char[](JDK8 及之前)或 byte[] + coder(JDK9+)被 final 修饰,数组引用不可改;
- 所有修改方法(concat、substring、replace、toUpperCase等)都不动原对象,而是 new 一个新 String;
- 不可变带来线程安全——多个线程读同一个字符串,完全不用同步;也支撑了常量池复用,避免重复创建。
分清两种创建方式,一眼看出内存位置
这是面试必考对比点,核心就看是否走常量池:
- String s = "abc" → JVM 先查字符串常量池,有则复用,无则新建并入池;对象在常量池(逻辑上属于堆的一部分,JDK7+起在堆中);
- String s = new String("abc") → 一定在堆中新建对象,同时常量池里也会确保存在 "abc"(如果还没有),但堆中对象和池中对象是两个独立实例;
- 所以
s1 == s2判断地址时,字面量赋值之间可能为 true,字面量与 new 创建之间一定为 false。
掌握 intern() 的真实作用
很多人误以为 intern() 是“把对象放回常量池”,其实它做的是“返回常量池中对应字符串的引用”:
立即学习“Java免费学习笔记(深入)”;
- 调用 s.intern() 时,JVM 检查常量池是否有内容相同的字符串;
- 如果有,直接返回池中那个引用;如果没有,就把该字符串内容加入池,并返回新加入的引用;
- 特别注意:
new String("abc").intern() == "abc"为 true,但new String("abc") == "abc".intern()仍为 false —— 因为左边是堆对象,右边是池引用。
遇到拼接题,先看编译期还是运行期
字符串拼接结果是否进常量池,取决于是否能在编译期确定:
-
"a" + "b" + "c"→ 全是字面量,编译器优化为"abc",直接进常量池; -
str1 + "b"(其中 str1 是变量)→ 运行期拼接,用 StringBuilder 实现,结果在堆中; -
"ab" + new String("c")→ 含 new 对象,整个表达式无法编译期确定,结果也在堆中。
不复杂但容易忽略,真正理解了底层行为,面试时哪怕遇到变形题也能当场分析清楚。


















