java String类型的变量和常量做“+”运算时发生了什么
在Java中,String常量进行"+"运算时,编译器会进行常量折叠优化(如"Hello" + "World"直接合并为常量池中的"HelloWorld");而涉及变量时(如str1 + str2),编译器会隐式转换为StringBuilder的append操作,每次拼接均创建新String对象,导致频繁内存分配和性能开销,因此在循环或高频拼接场景中必须使用StringBuilder而非+运算符以避免效率问题。
当Java中String类型的变量和常量使用"+"运算符进行拼接时,实际上发生了以下过程:
1. 编译期优化(常量拼接)
如果拼接的是编译期可以确定的常量,JVM会进行常量折叠(Constant Folding)优化:
- 例如:String str = "Hello, " + "World!"; 会被编译器在编译阶段直接优化为 String str = "Hello, World!";
- 这种情况下,字符串拼接不会产生额外的临时对象,而是直接使用常量池中的字符串
2. 运行时处理(涉及变量)
如果拼接中包含变量,Java编译器会将其转换为StringBuilder操作:
-
例如:String result = str1 + str2; 会被编译为:
String result = new StringBuilder().append(str1).append(str2).toString(); -
这个过程的内部机制:
- 隐式创建StringBuilder对象
- 调用append()方法添加字符串
- 最后调用toString()生成新字符串
3. 重要特点
- 字符串不可变性:Java中的String是不可变对象,每次拼接都会创建新的String对象
- 性能问题:在循环中使用+=操作符会导致严重性能问题,因为每次循环都会:
- 创建新的StringBuilder对象
- 复制现有内容
- 添加新内容
- 调用toString()生成新字符串
- 产生大量临时对象和内存拷贝
4. 实际示例
String str1 = "str";
String str2 = "ing";
String str3 = "str" + "ing"; // 编译期优化,常量拼接
String str4 = str1 + str2; // 运行时转换为StringBuilder
String str5 = "string";
// 结果分析
System.out.println(str3 == str4); // false(str3来自常量池,str4是新对象)
System.out.println(str3 == str5); // true(都是常量池中的"string")
System.out.println(str4 == str5); // false(str4是新创建的对象)
5. 优化建议
- 避免在循环中使用+=:应改用StringBuilder或StringBuffer
- 使用预分配容量:StringBuilder sb = new StringBuilder(estimatedSize);
- 对于单线程环境:优先使用StringBuilder(比StringBuffer更快)
- 对于多线程环境:使用StringBuffer(线程安全)
- 对于带分隔符的拼接:使用StringJoiner(Java 8引入)
6. 为什么需要这些优化?
在10万次字符串拼接测试中:
- 使用+运算符:平均耗时420ms
- 使用StringBuilder:平均耗时12ms(性能提升35倍)
这充分说明了在需要频繁拼接字符串的场景中,正确使用StringBuilder可以带来显著的性能提升。
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 软件从业者Hort
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果

