Java 何时应明确使用StringBuilder?

Java 何时应明确使用StringBuilder?,java,string,concatenation,stringbuilder,Java,String,Concatenation,Stringbuilder,据我所知,当我执行stringbaz=“foo”+“bar”+“123”时,Java编译器会在内部用StringBuilder替换表达式。然而,我们的Java老师告诉我们,总是显式地使用StringBuilder是一个很好的实践 我假设在连接内部循环时只需显式使用StringBuilder,如中所示,这是否正确?在其他情况下,是否应该显式使用StringBuilder而不是+或+=?它比“内部循环”更通用—您可以随时对多个语句进行串联,而不需要中间结果作为字符串。例如: StringBuilde

据我所知,当我执行
stringbaz=“foo”+“bar”+“123”
时,Java编译器会在内部用
StringBuilder
替换表达式。然而,我们的Java老师告诉我们,总是显式地使用
StringBuilder
是一个很好的实践

我假设在连接内部循环时只需显式使用StringBuilder,如中所示,这是否正确?在其他情况下,是否应该显式使用
StringBuilder
而不是
+
+=

它比“内部循环”更通用—您可以随时对多个语句进行串联,而不需要中间结果作为字符串。例如:

StringBuilder builder = new StringBuilder("Start");
if (someCondition) {
    builder.append("Foo");
}
if (someOtherCondition) {
    builder.append("Bar");
}
builder.append("End");
String result = builder.toString();
你可以这样写:

String result = "Start" + (someCondition ? "Foo" : "")
    + (someOtherCondition ? "Bar" : "") + "End";
。。。这变得很难理解。如果
if
主体中有更多的语句,那么它甚至可能不可行

要更正问题中的某些内容,请执行以下操作:

据我所知,当我执行String baz=“foo”+“bar”+“123”时,java编译器会在内部用StringBuilder替换表达式

不,当您编写该表达式时,编译器会识别出它是一个编译时常量,并用

String baz = "foobar123";
这是不显式使用
StringBuilder
的一个很好的理由-上面的代码在执行时显然比

String baz = new StringBuilder("foo").append("bar").append("123").toString();

当它不是编译时常量时,Java编译器将使用
StringBuilder
执行连接,通常比显式使用
StringBuilder
更容易理解代码,但不会影响性能。我怀疑你的老师要么没有正确理解字符串连接,要么只是在其他地方读到你应该使用
StringBuilder
,而没有完全理解什么时候合适。

欧比万说过,只有西斯认为是绝对的或类似的

很好,您知道Java编译器在内部使用
StringBuilder
替换字符串上的“+”。这就是编译器的作用:使生活更轻松

除非您有循环(如链接的大小写)或Jon Skeet示例中的条件句,否则这主要是可读性和易于维护的问题

替换

return "User " + userName + " said";

使代码更长,可能更难修改,更有可能强制换行,并提高性能

但是,当加法不仅适用于字符串,而且还涉及数字时,使用
StringBuilder
的解决方案有时可能更具可读性

return "User" + a + b + " said: " + (c + d);
可能更令人困惑的是:

return new StringBuilder().append("User ").append(a).append(b)
  .append(" said: ").append(c+d).toString();  

但这主要是观点和编码风格的问题。“应该”在这里不是一个好词。

它们也适用于用字符串实现C#'s'out'关键字。范例

public int getInt(StringBuilder error)
{
    int retVal = 0;

    if (someErrorOccured)
        error.append("Couldn't get int because of...");
    else
        retVal = whatItsSupposedToBe;

    return retVal;
}

总是显式地使用StringBuilder
-这不是一个好做法。您将牺牲代码可读性以获得0.0000000000001%的性能增益。在循环中追加数千个字符串时,请使用StringBuilder。我不知道您的java老师为什么如此热衷于使用StringBuilder。StringBuilder很酷,除了java之外,其他都是内部处理的。你的老师错了。您是对的。您是错的,
String baz=“foo”+“bar”+“123”
将在编译时替换为
String baz=“foobar123”
。编译时常量字符串串联在编译时完成。此外,编译器可能会用
StringBuilder
替换非常量字符串连接,但没有义务这样做。感谢您和其他人提供的详细答案,现在一切都清楚多了。你是dernc.c库的作者Jon Skeet吗?因为我在当前的项目中使用的是java端口:)只是偶然发现了这一点——我不相信C#在默认情况下会在下面使用StringBuilder?你知道为什么C#和Java之间存在差异吗?我以前一直想知道为什么C#不只是帮你解决这个问题。@user2711115:是的,我是dernc(作为Adikted的一部分)的作者,尽管我似乎记得Simon Tatham写了所有棘手的部分…Jon,老实说,
String result=“Start”+(someCondition?“Foo”:“)+(其他条件?“条”:“”)+“结束”
对我来说实际上比SB variant更易读……而且它也更简短。C背景和数十年来使用三元的习惯使我习惯于不费吹灰之力地阅读这样的语句。@vaxquis:它是否对你所有的同事来说更易读可能是另一回事:)我通常也是三元运算符的粉丝,但也有一些限制。正如我所说的,在那些块中可能还有更多。我只想重复我自己-
return“User”+a+b+”说:“+(c+d)
对我来说仍然比后一个版本更具可读性,特别是如果数字的命名合理的话——还要注意,您很少使用两个相邻的数字,中间没有任何分隔符;我还没有看到任何现实生活中的例子,实际上会使用SB来提高清晰度——不过,我想说,混淆事物是好的。
public int getInt(StringBuilder error)
{
    int retVal = 0;

    if (someErrorOccured)
        error.append("Couldn't get int because of...");
    else
        retVal = whatItsSupposedToBe;

    return retVal;
}