最后更新:2026-11-01 · 基于第 1 次作答
结论:a == b为 true——"a"+"b"是编译期常量折叠,b与"ab"指向同一字符串常量池条目;==比较的是引用。 关键词:编译期常量折叠 · 字符串常量池 · intern 边界:若任一操作数是运行期变量(非 final/非编译期常量),则走运行期拼接,==为 false。
核心考点定位:考察字符串"编译期常量 vs 运行期对象"的引用身份比较;面试官想看到"== 比较引用 + 常量折叠何时发生 + 常量池 intern",而非只背"== 比地址"。
机制链(≥3 环):
String a = "ab" → 字面量在编译期放入字符串常量池 → a 指向常量池中的 "ab" 实例。String b = "a" + "b" → 两个操作数都是编译期常量(字面量)→ 编译期常量折叠为 "ab" → b 同样指向常量池中同一个 "ab" 条目 → a == b 为 true。String c = new String("ab") → new 强制在堆上新分配对象 → c 的引用与常量池条目不同 → c == a 为 false,但 c.equals(a) 为 true。String s1 = "a"; String b2 = s1 + "b"; → s1 是运行期变量 → 编译期无法折叠 → 运行期走 StringBuilder.append 生成堆上新 String → b2 == a 为 false。证据锚点:
"ab":字面量,编译期入池"a" + "b":编译期常量折叠new String("ab"):强制堆上新对象StringBuilder.append:运行期拼接实现intern():运行期字符串池化String#equals:内容比较(String 重写)final:编译期常量的必要条件之一==:引用比较对比与权衡:
| 表达式 | 编译期折叠 | 是否常量池 | a == b |
|---|---|---|---|
"ab" | — | 是 | 基准 |
"a" + "b" | 是 | 是 | true |
s1 + "b"(s1 变量) | 否 | 否(堆) | false |
new String("ab") | 否 | 否(堆) | false |
"a" + "b"(final 变量) | 是 | 是 | true |
常见误区:
== false" → 正确:字面量拼接是编译期常量折叠,指向常量池同一条目 → true → 为什么:折叠在编译阶段完成,不产生运行期对象。== 和 equals 都能比较字符串内容" → 正确:== 比较引用,equals 比较内容 → 为什么:String 重写了 equals 为内容比较,== 仍是引用比较。intern() 没有意义" → 正确:intern() 把运行期字符串放入常量池并返回池内引用,可池化复用 → 为什么:用于运行期动态字符串的复用,但需注意常量池内存。适用边界:
== 判断;需要内容判断 → equals。== 不可靠;需池化运行期字符串 → intern(注意池内存)。equals/Objects.equals;循环拼接用显式 StringBuilder。final 常量表达式)static final 与普通 final 在折叠上的区别intern() 做了什么?StringBuilder 与 + 的关系?+ 拼接被转为 StringBuilder.append 链StringBuilder 避免反复创建equals 不用 ==?== 比较引用,equals 比较内容;Objects.equals 空安全String 的 equals 实现(先 == 快路径再逐字符)【结论】 a == b 为 true——"a"+"b" 是编译期常量折叠,与 "ab" 指向同一个字符串常量池条目;== 比较的是引用。
【三点】
第一,字面量入池:"ab" 编译期进入字符串常量池,a 指向该条目。
第二,常量折叠:"a"+"b" 两个操作数都是字面量,编译期折叠成 "ab",b 也指向同一池条目,所以 == 为 true。
第三,何时为 false:一旦换成运行期变量拼接(s1 + "b")或 new String("ab"),就生成堆上新对象,== 为 false、equals 为 true。
【边界】 == 只比较引用,比内容必须 equals;常量折叠仅限字面量/final 编译期常量,运行期拼接不折叠;需要复用运行期字符串用 intern()。
题目:String a="ab"; String b="a"+"b"; a==b 吗?
难度:medium
标签:java/string, java/collections, general/knowledge, difficulty/medium
评分:⭐☆☆☆☆(1/5)
==比对的是内存位置,如果不将ab放入持久化空间,那么==是返回false的,需要通过equals比较才是值比较;
评分:⭐☆☆☆☆(1/5)
优点:记得 == 比较引用地址、equals 比较值。
不足:结论错误。"a"+"b" 是编译期常量折叠,b 与 "ab" 指向同一字符串常量池条目 → a==b 为 true。你所说的"没放入持久化空间则为 false"是运行时拼接(new String/变量拼接)的情形,用错了场景。
补充:补①区分编译期常量(字面量/final 拼接→intern→true)vs 运行期拼接(变量/new→堆上新对象→false);②== 比较引用、equals 比较内容;③intern() 池化运行期字符串。
完整讲解见上方「完整讲解(权威版)」