Java中字符串+拼接在编译期被转为StringBuilder.append(),常量表达式可能被折叠;运行期循环中使用会频繁创建StringBuilder对象,导致性能下降。

Java 中用 + 拼接字符串,表面看是语法糖,但面试常考它背后的编译器行为和运行时逻辑。解题关键不是背结论,而是理清“谁在什么时候创建了什么对象”。
编译期:+ 被自动转成 StringBuilder.append()
Java 编译器(javac)在编译阶段就把常量字符串的 + 表达式优化为 StringBuilder 调用。比如:
String s = "a" + "b" + "c";
编译后等效于:
立即学习“Java免费学习笔记(深入)”;
String s = new StringBuilder().append("a").append("b").append("c").toString();
注意:这是**编译期一次性生成**,不涉及运行时反复创建 StringBuilder。
- 所有操作数都是编译期常量(字面量或 final 静态变量)时,整个表达式可能进一步被常量折叠,直接变成
"abc"存入常量池 - 只要有一个非常量(如普通变量、方法返回值),编译器就无法折叠,只能生成 StringBuilder 代码
运行期:循环中用 + 会频繁新建 StringBuilder
真正性能陷阱出现在循环里:
String s = "";
for (int i = 0; i s += "x";
}
每次 += 都会触发:
- 新建一个 StringBuilder 对象(在堆上)
- 把当前 s 和 "x" append 进去
- 调用 toString() 创建新 String
- 旧 StringBuilder 和中间 String 成为垃圾
100 次循环 → 约 100 个 StringBuilder + 100 个临时 String,GC 压力明显。
对比 StringBuilder 手动复用的优势
手动写 StringBuilder 就能避免重复创建:
StringBuilder sb = new StringBuilder();
for (int i = 0; i sb.append("x");
}
String s = sb.toString();
- 只创建 1 个 StringBuilder 实例,内部 char[] 可扩容复用
- 最终仅生成 1 个 String 对象
- 没有中间无用对象,内存和 CPU 更友好
常量池与 new String() 的干扰项要分清
面试题常混入 == 和 equals() 判断,本质是考察字符串存储位置:
-
"abc" == "abc"→ true(都从常量池取,地址相同) -
new String("abc") == "abc"→ false(前者在堆,后者在常量池) -
new String("abc").equals("abc")→ true(比较内容)
这些和 + 优化无关,但容易被拿来干扰判断。答题时先确认题干焦点是“拼接过程”,再决定是否展开常量池。


















