Java字符串拼接+的优化分两种:编译期常量直接合并为字面量;含变量时编译器插入StringBuilder链式调用;JDK9+改用invokedynamic动态选择最优策略;循环中+=仍每轮新建StringBuilder,应手动复用。

Java 字符串拼接用 + 运算符,底层是否优化、怎么优化,完全取决于操作数能否在编译期确定——不是统一走某条路径,而是分两种截然不同的机制。
编译期常量拼接:直接合并,不生成任何对象
当所有参与 + 的操作数都是编译期常量(如字符串字面量 "a"、final String、final int 等),javac 会在编译阶段就把整个表达式算出来,生成一个单一字符串字面量,存入常量池。
-
String s = "Hello" + " " + "World";→ 编译后等价于String s = "Hello World"; -
final String a = "Java"; final String b = "17"; String s = a + b;→ 同样折叠为"Java17" - 字节码中只有
LDC指令加载常量,没有StringBuilder、没有new、没有方法调用
运行期含变量拼接:编译器插入 StringBuilder 链式调用
只要有一个操作数是普通变量、方法返回值、或非 final 引用,javac 就无法折叠,转而生成等效的 StringBuilder 代码:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
String s = prefix + name + suffix;(prefix、name、suffix均为局部变量)→ 编译后类似:new StringBuilder().append(prefix).append(name).append(suffix).toString() - 自动处理类型转换:如
"age=" + age,会先调用String.valueOf(age)再 append - 默认使用
StringBuilder(非线程安全),不是StringBuffer;除非你显式写,否则不会加锁
JDK 9+ 的进阶优化:StringConcatFactory + invokedynamic
从 JDK 9 开始,javac 不再硬编码 new StringBuilder(),而是生成 invokedynamic 指令,由 JVM 运行时通过 StringConcatFactory 动态选择最优策略:
立即学习“Java免费学习笔记(深入)”;
- 策略包括
MH_INLINE_SIZED_EXACT(默认):直接操作字节数组,跳过 StringBuilder 的扩容和拷贝 - 仍保持语义一致:结果仍是不可变
String,行为与旧版等价,但更轻量 - 该优化对开发者透明,无需改代码,但依赖 JIT 热点识别;小规模拼接提升有限,大规模或高频场景收益明显
循环中慎用 +=:编译器不帮你复用对象
即使单个 + 被优化成 StringBuilder,循环里写 result += str 仍会每轮都新建 StringBuilder 实例:
- 每次
+=都对应一次new StringBuilder().append(old).append(new).toString() - 旧内容反复拷贝,时间复杂度退化为 O(n²),尤其数据量大时性能断崖式下降
- 正确做法是手动声明并复用一个
StringBuilder实例,自己控制容量和生命周期

















