java字符串拼接根据编译期是否可确定选择不同路径:常量拼接在编译期合并,零开销;含变量时jdk8及以前默认用stringbuilder,jdk9+改用invokedynamic动态优化;循环拼接应手动复用stringbuilder。

Java 中 String 拼接不是简单“连起来”,而是 JVM 根据上下文动态选择最优路径的过程。关键看拼接内容是否在编译期可确定 —— 这直接决定是走编译期优化,还是运行时构建。
编译期常量拼接:直接合并,零运行开销
当所有参与拼接的都是字面量或 final 修饰的编译期常量(如 "a" + "b" 或 final String x = "hello"; final String y = "world"; String z = x + y;),JVM 在编译阶段就完成计算,字节码中只保留一个 LDC "ab" 或 LDC "helloworld" 指令。整个过程不创建任何 StringBuilder,也不生成中间 String 对象,性能最高。
运行时变量拼接:默认委托给 StringBuilder
只要拼接表达式中含非常量变量(如普通局部变量、方法参数、返回值等),JVM 就无法在编译期确定结果。此时字节码会显式生成:
- NEW java/lang/StringBuilder(每次拼接都新建)
- INVOKEVIRTUAL append(...)(多次调用)
- INVOKEVIRTUAL toString()(最终转成 String)
这意味着:循环内写 result += s,每轮都会 new 一个 StringBuilder、append 一次、toString 一次 —— 对象频繁创建+数组反复复制,时间复杂度趋近 O(n²)。
JDK9+ 的优化升级:invokedynamic + StringConcatFactory
从 JDK9 开始,+ 拼接不再硬编码为 StringBuilder 调用,而是通过 invokedynamic 指令绑定到 StringConcatFactory.makeConcatWithConstants。JVM 运行时根据拼接模式(长度、类型、是否含 null)自动选择最高效策略:可能复用 char[]、跳过冗余拷贝、甚至内联为紧凑字节码。开发者无需改代码,但底层更智能、更轻量。
手动优化的核心原则:复用 vs 创建
编译器不会帮你把循环里的 += 提取到外部 —— 这必须由你主动做:
- 循环拼接:在循环外声明
StringBuilder sb = new StringBuilder();,循环内只调sb.append(...),最后sb.toString() - 多线程环境:若需并发拼接,改用
StringBuffer(同步保障),但通常推荐用局部StringBuilder+ 显式传参,避免锁竞争 - 集合拼接:优先用
String.join(",", list)或Collectors.joining(),它们内部已做容量预估和复用优化
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











