如果编译器自动将字符串连接转换为StringBuilder,为什么要显式使用StringBuilder?

pet*_*ter 36 java stringbuilder

可能重复:
String中的StringBuilder与字符串串联在toString()中

我想知道,因为编译器内部使用StringBuilder在执行字符串连接时附加2个字符串,那么问题是什么?如果字符串连接已经为你完成了工作,我为什么要使用StringBuilder呢?还有其他具体原因吗?

Mar*_*ers 65

正如您所提到的,您不应该使用StringBuilder简单的字符串连接表达式来代替a + " = " + b.后者输入速度更快,更易于阅读,编译器StringBuilder无论如何都会在内部使用,因此重写它没有性能优势.

但是StringBuilder,如果要在循环中连接大量字符串,则非常有用.以下代码效率低下.它需要O(n 2)次运行并创建许多临时字符串.

String result = "";
for (int i = 0; i < foo.length; ++i)
{
    result += bar(foo[i]);  // Bad
}
Run Code Online (Sandbox Code Playgroud)

试试这个:

StringBuilder sb = new StringBuilder();
for (int i = 0; i < foo.length; ++i)
{
    sb.append(bar(foo[i]));
}
String result = sb.toString();
Run Code Online (Sandbox Code Playgroud)

编译器仅优化简单a + b + c表达式.它无法自动优化上述代码.

  • @ user1389813使用`+ =`将在每次迭代时创建一个新的`StringBuilder`,复制源字符串,追加你连接的任何内容(也可能需要一个副本),然后将它转换为`String`(这是另一个复制).使用一个`StringBuilder`可以避免不必要的复制. (4认同)
  • @JohanSjöberg是的,事实上确实如此.做`result + = bar(foo [i])`会产生类似(假设javac)`result = new StringBuilder().append(result).append(foo [i]).toString()`.请注意,这比使用一个`StringBuilder`要多得多. (3认同)
  • @ user1389813:这是因为在第一个示例中,Java的优化器不知道如何保留一个StringBuilder来完成循环中的所有连接 - 它看不到足够的知识,你知道你总是会连接到同一个否则永远不会看到循环外部的字符串,所以每次必须添加到`result`时它会创建一个新字符串. (3认同)
  • @cHao是的,我完全了解理论 - 但我正在讨论手头的实际编译器(假设它是javac).javac不再显式执行任何*real*优化,而且它从未做过复杂的优化.它所做的是持续折叠和DCE传递. (2认同)