← 每日面试题 学习看板

String a = "ab"; String b = "a" + "b"; a == b 吗?

面试题/00java/01Java 基础/02 数据类型/String a = "ab"; String b = "a" + "b"; a == b 吗?.md

完整讲解(权威版)

最后更新:2026-11-01 · 基于第 1 次作答

L1 · 30 秒速记

结论:a == b 为 true——"a"+"b" 是编译期常量折叠,b 与 "ab" 指向同一字符串常量池条目;== 比较的是引用。 关键词:编译期常量折叠 · 字符串常量池 · intern 边界:若任一操作数是运行期变量(非 final/非编译期常量),则走运行期拼接,== 为 false。

L2 · 核心讲解

核心考点定位:考察字符串"编译期常量 vs 运行期对象"的引用身份比较;面试官想看到"== 比较引用 + 常量折叠何时发生 + 常量池 intern",而非只背"== 比地址"。

机制链(≥3 环):

  1. String a = "ab" → 字面量在编译期放入字符串常量池 → a 指向常量池中的 "ab" 实例。
  2. String b = "a" + "b" → 两个操作数都是编译期常量(字面量)→ 编译期常量折叠为 "ab" → b 同样指向常量池中同一个 "ab" 条目 → a == b 为 true。
  3. 若 String c = new String("ab") → new 强制在堆上新分配对象 → c 的引用与常量池条目不同 → c == a 为 false,但 c.equals(a) 为 true。
  4. 若 String s1 = "a"; String b2 = s1 + "b"; → s1 是运行期变量 → 编译期无法折叠 → 运行期走 StringBuilder.append 生成堆上新 String → b2 == a 为 false。

证据锚点:

对比与权衡:

表达式编译期折叠是否常量池a == b
"ab"—是基准
"a" + "b"是是true
s1 + "b"(s1 变量)否否(堆)false
new String("ab")否否(堆)false
"a" + "b"(final 变量)是是true

常见误区:

  1. 错误:""a"+"b" 会 new 新字符串,所以 == false" → 正确:字面量拼接是编译期常量折叠,指向常量池同一条目 → true → 为什么:折叠在编译阶段完成,不产生运行期对象。
  2. 错误:"只要有一个变量参与拼接就是编译期常量" → 正确:必须是 final + 编译期常量(字面量/常量表达式)才折叠;非 final 变量 → 运行期拼接 → false → 为什么:运行期变量值编译期未知,无法折叠。
  3. 错误:"== 和 equals 都能比较字符串内容" → 正确:== 比较引用,equals 比较内容 → 为什么:String 重写了 equals 为内容比较,== 仍是引用比较。
  4. 错误:"intern() 没有意义" → 正确:intern() 把运行期字符串放入常量池并返回池内引用,可池化复用 → 为什么:用于运行期动态字符串的复用,但需注意常量池内存。

适用边界:

延伸追问(≥3)

  1. 常量折叠的条件是什么?
  1. intern() 做了什么?
  1. StringBuilder 与 + 的关系?
  1. 为什么判字符串用 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()。

面试记录 2026-11-01(第 1 次)

题目: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() 池化运行期字符串。

完整讲解见上方「完整讲解(权威版)」