java字符串拼接分两种:纯字面量或final常量时编译期直接折叠为常量,无stringbuilder;含非常量变量时编译器自动转为stringbuilder.append()调用;循环中+=会重复创建stringbuilder,应显式复用。

Java 中字符串直接用 + 相加,并不是在运行时调用 StringBuilder,而是由 javac 编译器在编译期自动重写为 StringBuilder 调用代码——但这个过程只发生在“含变量”的拼接中;如果是纯字面量,则连 StringBuilder 都不出现,直接折叠成常量。
关键要分清两种场景:
编译期常量折叠:不生成 StringBuilder,一步到位
当所有操作数都是编译期可确定的常量时(如字符串字面量、或 final String 且初始化值也是字面量),编译器会跳过 StringBuilder,直接把结果算出来,存进 class 文件的字符串常量池。
例如:
-
"a" + "b" + "c"→ 编译后等价于"abc"(字节码中是ldc "abc") -
final String x = "hello"; final String y = "world"; String s = x + y;→ 同样折叠为"helloworld"
这种写法没有对象创建、没有方法调用、没有运行时开销。
含变量时:编译器插入 StringBuilder 构造和 append
只要有一个操作数不是编译期常量(比如普通 String s = "a";,或 getMsg() 返回值),编译器就无法提前计算,必须生成运行时拼接逻辑。此时 javac 会把 a + b + c 自动转成等效字节码:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
new StringBuilder() .append(a) .append(b) .append(c) .toString();
注意三点:
- 这个转换发生在编译阶段,不是 JVM 运行时 JIT 做的优化
-
StringBuilder是默认选择(非线程安全,性能高),不是StringBuffer - 编译器还会自动处理类型转换:
"num=" + 123会被转为append(String.valueOf(123))
循环中 += 是典型陷阱
写成这样:
String s = "";
for (int i = 0; i <p>每次 <code>+=</code> 都被编译为: </p><pre class="brush:java;toolbar:false;">s = new StringBuilder().append(s).append("x").toString();意味着每轮都新建 StringBuilder、复制旧内容、再丢弃——时间复杂度接近 O(n²),对象爆炸。
正确做法是:
- 显式声明
StringBuilder sb = new StringBuilder(); - 循环内只调
sb.append("x") - 最后一次调
sb.toString()
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










