You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中String链式拼接运算符`+`的内部处理机制(Java 9及之后版本)

Java中String链式拼接运算符+的内部处理机制(Java 9及之后版本)

你提的这个问题刚好戳中了Java 9对字符串拼接优化的核心点,我来一步步给你拆解内部细节,还有你关心的装箱问题~

首先先看你给出的示例代码:

import java.util.Random;

public class StringConcatCompilerOptimization
{
    private static long compute() {
        var random = new Random();
        var l = random.nextLong();
        return l;
    }
    public static void main(String[] args)
    {
        int i = 1;
        byte b = 120;
        boolean l = true;
        String s = "Hello" + i + compute() + b + l + "world!"; // + concatenation chain
        System.out.println(s);
    }
}

对应的javap反编译输出:

Compiled from "StringConcatCompilerOptimization.java"
public class StringConcatCompilerOptimization {
  public StringConcatCompilerOptimization();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: istore_1
       2: bipush        120
       4: istore_2
       5: iconst_1
       6: istore_3
       7: iload_1
       8: invokestatic  #14                 // Method compute:()J
      11: iload_2
      12: iload_3
      13: invokedynamic #19,  0             // InvokeDynamic #0:makeConcatWithConstants:(IJBZ)Ljava/lang/String;
      18: astore        4
      20: getstatic     #23                 // Field java/lang/System.out:Ljava/io/PrintStream;
      23: aload         4
      25: invokevirtual #29                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      28: return
}

Java 9前后的拼接逻辑差异

正如你所说,Java 9之前,编译器会把"Hello" + i + compute() + b + l + "world!"这类链式拼接转换成一串StringBuilder.append()调用,每次拼接都要操作StringBuilder的实例,虽然已经比直接字符串相加(每次生成新String)高效,但还是有对象创建和方法调用的开销。

而Java 9及之后,编译器会把这段代码转换成invokedynamic指令,调用makeConcatWithConstants方法,这是一种更灵活、更高效的实现。


invokedynamic调用后的内部流程

当JVM执行到这条invokedynamic指令时,会触发以下步骤:

  1. 引导方法调用:JVM会调用StringConcatFactory.makeConcatWithConstants这个JDK内部的工厂方法,它的作用是生成一个专门的字符串拼接函数。
  2. 模板预编译:工厂方法会根据传入的常量字符串(也就是你代码里的"Hello"和"world!")生成一个拼接模板,把变量要插入的位置标记出来,类似内部高效格式的占位符模板。
  3. 生成并缓存拼接实现:工厂方法会动态生成一个适配当前参数类型(int、long、byte、boolean)的拼接实现类,这个实现会被JVM缓存起来,后续如果遇到相同模板和参数类型的拼接,会直接复用这个实现,不用重新生成。
  4. 参数填充与拼接:最后,JVM会把变量参数(i的值、compute()返回的long值、b的值、l的值)传入这个拼接实现,实现会直接把基本类型转成字符串,填充到模板的对应位置,最终生成完整的拼接字符串。

关于装箱的问题

你问到的装箱是不会发生的,这也是这个优化的亮点之一:

  • 传统的StringBuilder.append()对于基本类型,其实也是直接调用append(int)、append(long)这类重载方法,内部会调用Integer.toString()等静态方法转字符串,不会装箱。
  • 而makeConcatWithConstants更进一步,它直接针对传入的基本类型参数调用对应的toString静态方法(比如Integer.toString(i)、Long.toString(compute的返回值)),完全跳过了装箱步骤,直接把基本类型转成字符串,性能比之前的StringBuilder方式还要略胜一筹。

总结一下,Java 9之后的字符串拼接通过invokedynamic实现了动态生成高效拼接代码,既避免了大量的append方法调用,又省去了装箱开销,是JDK对字符串操作的一次重要性能优化。

备注:内容来源于stack exchange,提问作者nickolay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 09:13:03