Java中String不可变,+拼接每次创建新对象;底层为final数组,修改需新建对象;编译器将含变量的+转为StringBuilder操作,循环中s+="x"会频繁创建临时对象。

因为Java中String是不可变对象,每次用+拼接,JVM都必须创建新对象来承载合并后的内容,而不是修改原字符串。
String不可变性是根本原因
String类底层由final修饰的字符数组(JDK9+为byte数组)构成,一旦初始化就不能更改内容或长度。所以任何“修改”操作——包括+拼接——都只能通过新建对象实现。
- 原字符串对象保持不变,只是引用被覆盖
- 新字符串需分配新内存,复制旧内容 + 新内容
- 频繁拼接会持续产生临时String和中间StringBuilder对象
编译器对+的翻译机制
Java编译器不会直接执行字符串相加,而是按规则重写为StringBuilder调用:
- 无变量的字面量拼接(如
"a"+"b"+"c")在编译期就优化为"abc",不产生运行时开销 - 含变量的拼接(如
s + "x")会被转成类似new StringBuilder().append(s).append("x").toString() - 在循环中写
s += "x",每次迭代都会新建一个StringBuilder和一个String对象
典型低效场景:循环拼接
以下代码看似简洁,实则代价高昂:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
立即学习“Java免费学习笔记(深入)”;
String s = "";
for (int i = 0; i < 1000; i++) {
s += i;
}
它等价于:
- 第1次:创建StringBuilder → append("") → append("0") → toString() → 新String
- 第2次:再建StringBuilder → append(前次结果) → append("1") → toString() → 新String
- ……重复1000次,生成约2000个临时对象(1000个StringBuilder + 1000个String)
真正高效的做法
把可变拼接逻辑交给专门的工具类,避免重复构造:
- 单线程场景:用
StringBuilder,提前预估容量(如new StringBuilder(1024)) - 多线程共享拼接:用
StringBuffer(同步但稍慢) - 拼接已知集合:优先用
String.join(", ", list),内部已优化 - 仅两次拼接且不含循环:
+仍可接受,JVM优化足够

















