StringBuilder/StringBuffer的toString()是否生成新不可变String及规避方法
关于StringBuilder/StringBuffer的toString()方法的疑问解答
嘿,这个问题问到点子上了,这也是很多Java开发者刚接触可变字符串时容易搞混的细节,我来逐一给你解释清楚:
1. StringBuilder或StringBuffer的toString()是否会创建新的不可变String?
答案是肯定的。我们可以直接看JDK源码里的实现:
- StringBuilder的
toString()方法会调用new String(value, 0, count),基于自身内部的字符数组创建一个全新的String实例。 - StringBuffer的实现逻辑类似,只不过它的方法是线程安全的(加了
synchronized修饰),但最终同样会生成新的String对象。
这个新创建的String和普通String一样,是完全不可变的——因为String类的字符存储数组(JDK9+为byte数组)被final修饰,且没有对外暴露修改内部数组的方法,一旦生成就无法被改变。
2. 调用toString()会在字符串常量池中生成新的String吗?如何避免?
首先明确:默认情况下不会。
String常量池(JDK7及以后存放在堆中)里的字符串,一般来自这几种场景:
- 直接编写的字符串字面量(比如
"hello") - 主动调用String的
intern()方法的字符串对象 - 编译期可确定的字符串拼接结果(比如
"a"+"b"会被编译成"ab"直接入池)
而StringBuilder.toString()生成的String对象,默认存放在堆的普通区域,不会自动进入常量池。只有当你主动调用这个String对象的intern()方法时,才会把它的引用放入常量池(前提是常量池里没有相同内容的字符串)。
所以如果要避免在常量池生成对应的String,只要不调用该String对象的intern()方法就可以了。日常开发中如果没有特殊需求(比如字符串复用、减少内存占用),其实根本不需要调用intern(),自然也就不会在常量池生成额外实例。
内容的提问来源于stack exchange,提问作者sam
相关产品推荐
相关产品推荐

