让我们考虑您的第一个示例:
String a="";
for(int i=0;i++<9;)
a+=i;
这段代码将像这样执行:
String a="";
a=new StringBuilder(a).append(0).toString();
a=new StringBuilder(a).append(1).toString();
a=new StringBuilder(a).append(2).toString();
a=new StringBuilder(a).append(3).toString();
a=new StringBuilder(a).append(4).toString();
a=new StringBuilder(a).append(5).toString();
a=new StringBuilder(a).append(6).toString();
a=new StringBuilder(a).append(7).toString();
a=new StringBuilder(a).append(8).toString();
a=new StringBuilder(a).append(9).toString();
因此,对于每个循环迭代,您都会StringBuilder
从字符串中创建一个新的(每次分配一个新的内部缓冲区),每次都char[]
将其转换回。String
另一方面,在第二种情况下,您将有效地拥有
StringBuilder a=new StringBuilder("").append(0).append(1).append(2).append(3)
.append(4).append(5).append(6).append(7).append(8).append(9);
因此,您将只有一个StringBuilder
只有一个内部char[]
缓冲区(在您的情况下它不会被重新分配,因为所有附件都不会超过 的初始容量16
)。所以它更快,因为你有更少的对象并且没有任何东西被复制多次。
写入a=new String("")
是无用的,因为除了已经拥有的空字符串(在加载类常量池期间创建和实习)之外,您还将拥有一个空字符串。除了额外的空字符串(在第一次循环迭代和垃圾收集后将变得未使用)之外,它与第一种情况没有什么不同。
请注意,在 JLS 中没有明确指定如何实现字符串连接(使用隐式StringBuilder
或其他技术),但通常 java 编译器使用StringBuilder
.