java中含非final变量的字符串拼接不优化,因编译器无法静态判定值恒定,故生成stringbuilder代码;仅static final或字面量等真正编译期常量才折叠。

Java中 String 变量与字面量拼接(比如 "Hi, " + name),编译器不会做常量折叠,而是生成 StringBuilder 的构造和 append 调用——这是运行时行为,对象在堆上创建,结果字符串不进常量池。
为什么不算“纯常量”,所以不优化?
只要表达式里出现非 final 的局部变量(哪怕值是固定的,如 String name = "Alice"),JVM 就无法在编译期确定其值是否恒定。编译器只对真正可静态判定的常量(字面量、static final 字符串、编译期已知的基本类型)做合并。变量意味着运行时才绑定,必须留到执行阶段处理。
底层实际生成什么代码?
类似这样的源码:
String greeting = "Hello, " + name;
编译后等价于:
StringBuilder sb = new StringBuilder();sb.append("Hello, ");sb.append(name);String greeting = sb.toString();
注意:这个过程由 javac 自动插入,无需手动写 StringBuilder;但逻辑上完全一致。
final 修饰的变量是个例外
如果变量被声明为 final 且初始化为字面量,例如:
final String name = "Alice";<br>String s = "Hi, " + name;
此时 javac 会把它当作编译期常量,直接合并为 "Hi, Alice",存入常量池,不生成 StringBuilder 指令。这也是为什么 s == "Hi, Alice" 可能为 true 的原因。
常见误区提醒
很多人误以为 “有字面量就一定高效”,其实关键不在有没有字面量,而在有没有**可变引用**。哪怕只是 String s = "a" + args[0];,哪怕 args[0] 实际上是 "b",只要它不是编译期可推断的常量,就会走 StringBuilder 路径。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











