java string高频考点聚焦不可变性、常量池与==/equals语义差异:不可变性源于final修饰的底层数组和private封装,确保线程安全与常量池复用;常量池缓存字面量,new string()总在堆新建对象;==比较地址,equals比较内容。

Java String 面试题高频考点集中在三个底层逻辑上:不可变性、字符串常量池、以及 == 与 equals() 的语义差异。掌握这三点,就能覆盖 90% 的实际面试问题。
不可变性是理解一切的起点
String 对象一旦创建,内容无法修改——不是语法限制,而是设计契约:
- 底层 char[](JDK8)或 byte[](JDK9+)被 final 修饰,引用不可重赋;private 封装阻止外部篡改数组内容
- 所有“修改”操作(concat、substring、replace 等)都返回新对象,原对象不变
- 不可变带来线程安全、哈希码稳定(可作 HashMap key)、常量池复用等关键优势
字符串常量池决定对象创建逻辑
常量池是 JVM 方法区(JDK7+ 在堆中)的一块特殊内存区域,用于缓存字面量字符串:
- String s = "abc" → 先查池,无则创建并入池,s 指向池中对象
- String s = new String("abc") → 一定在堆新建对象(可能触发池中字面量创建),s 指向堆对象
- s.intern() → 若池中已有相同内容,返回池中引用;否则将该字符串引用加入池并返回
== 和 equals() 必须分清场景
这不是“哪个对”的选择题,而是“你到底想比什么”的判断题:
- == 比的是内存地址:常量池内同值字符串地址相同;new 出的对象地址总不同
- equals() 比的是字符序列内容:String 重写了该方法,先判地址再逐字符比较
- 常见陷阱:把 equals() 当 == 用(如 if (str.equals("null"))→ NPE;或误以为 new String("a") == "a" 成立
编译期优化与运行时拼接要分开看
字符串拼接行为取决于参与运算的是否全是编译期常量:
- "a" + "b" + "c" → 编译器直接优化为 "abc",进常量池,地址复用
- str1 + "b"(str1 是变量)→ 运行时通过 StringBuilder.append 构建,结果在堆中,不进常量池
- 频繁拼接用 StringBuilder(单线程)或 StringBuffer(多线程),避免大量临时 String 对象
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











