答案是:String核心考点围绕不可变性展开,涉及常量池与堆内存分布、字面量与new创建差异、+拼接的编译期优化与运行时机制。不可变性由final类、final数组引用、无修改方法共同保证,带来线程安全、哈希稳定、安全性等优势;字面量创建复用常量池,new创建必在堆中;编译期确定的拼接(如"ab"+"cd")优化为常量池对象,含变量拼接(如s1+s2)则运行时生成堆中对象,故s3=="abcd"为true而s4=="abcd"为false。

学Java字符串考点,别堆概念、别死记硬背。核心就三点:抓住不可变性这条主线,理清内存位置(常量池 vs 堆),再结合典型操作看它怎么影响对象创建和比较。面试官考的不是你会不会写“String s = "abc";”,而是你能不能一眼看出s == "abc"为什么有时true、有时false。
从不可变性出发,理解所有行为根源
String类被声明为final,内部字符数组(Java 9+是byte[])用final修饰,且没有提供任何修改内容的方法。这意味着:
- 每次拼接、截取、替换,都生成新对象,原对象不变
- 作为HashMap键安全可靠——内容不变,哈希值可缓存,不会因中途修改导致散列错乱
- 多线程读取无需同步——没人能改它,自然线程安全
- 密码、SQL语句等敏感字符串一旦构造完成,就不会被意外篡改
分清两种创建方式,搞懂对象在哪、有几个
这是面试必问,也是最容易混淆的地方:
-
字面量方式:
String s1 = "hello";→ JVM先查字符串常量池,有则复用,无则新建并放入池中 -
new方式:
String s2 = new String("hello");→ 一定在堆中新建对象;若常量池无"hello",还会额外在池中建一个 -
s1 == s2一定为false(地址不同),但s1.equals(s2)为true(内容相同) - 编译期确定的字面量拼接(如
"a"+"b")会被优化成单个字面量,仍走常量池
拼接操作背后的真实机制与性能选择
看似简单的+号,底层逻辑完全不同:
立即学习“Java免费学习笔记(深入)”;
- 两个字面量拼接(
"ab" + "c")→ 编译期直接优化为"abc",不运行时创建对象 - 含变量的拼接(
str + "c")→ 编译器自动转成StringBuilder.append()调用,但循环中反复用+会频繁创建中间对象 - 大量拼接场景必须用
StringBuilder(单线程)或StringBuffer(多线程),避免隐式对象爆炸 -
concat()方法每次都会新建String对象,效率低于StringBuilder,日常少用
常考陷阱题,一题串起多个知识点
比如这道高频题:
String s1 = "ab"; String s2 = "cd"; String s3 = "ab" + "cd"; String s4 = s1 + s2; System.out.println(s3 == "abcd"); // true System.out.println(s4 == "abcd"); // false原因很清晰:
-
s3是字面量拼接,编译期优化为"abcd",与常量池中字面量指向同一对象 -
s4含变量,运行时通过StringBuilder拼接,结果在堆中,不进常量池(除非显式调用intern()) - 所以前者地址相等,后者不等——本质还是编译期 vs 运行时、常量池 vs 堆的区别


















