在Java中使用“+”符号连接字符串

14

我有一个如下所示的巨大字符串:

String str = "aaaaaaa" 
        + "bbbbbbbb" 
        + "cccccccc" 
    .... 

        + "zzzzzzzz";  // about 200 lines long

这会浪费很多内存吗?是把它放在一行中还是使用 StringBuilder 更好呢? 这是为了创建一个长的sql语句。


6
更好的问题应该是,为什么要连接那么多行? - Makoto
1
@Makoto 你还有其他的方法吗? - javaguy
由于您正在用它来构建 SQL 查询,我建议您尝试使用更简洁的 API 来创建,比如 Criteria API - Makoto
5个回答

25

不会。如果您的所有字符串都是常量(如您的问题中一样),编译器将在编译时执行连接操作,这比使用StringBuilder版本性能更好。

否则,它将使用StringBuilder(或StringBuffer)来执行任何非常量部分的连接操作。

因此,以下代码的编译版本为:

String x = "a" + "b";

应该完全与以下内容相同:

String x = "ab";
请注意,“非常数”部分可能意味着您有时可以通过明智地使用括号获得(非常小的)额外效率。例如:

请注意,“非常数”部分可能意味着您有时可以通过明智地使用括号获得(非常小的)额外效率。例如:

int value = ...;
String x = "a" + value + "b" + "c";

...不如以下方式效率更低:

int value = ...;
String x = "a" + value + ("b" + "c");

...作为第一个追加"b""c"的单独操作。高效版本等同于:

int value = ...;
String x = "a" + value + "bc";

我不记得曾经将其用作合法的微优化,但至少它是一个值得关注的点。


3
编译器不应该为你做这种微小的优化吗?或者换句话说,是否存在任何foo的值,使得(foo + "a") + "b"foo + "ab"不同? - Ilmari Karonen
@IlmariKaronen:我想不到有什么办法,但这是我观察标准javac时发现的。不过,我认为这将是一种有效的优化。 - Jon Skeet
1
有没有不执行优化的方法? - javaguy

4
在当前的Java版本中,每个+(连接)操作都会自动编译为StringBuilderappend()操作。然而,如果它在循环内部,它会为每次迭代创建一个新的 StringBuilder ,从而抵消其效果-因此你最好明确地管理 StringBuilder

2
不需要。编译器会为您将其优化为StringBuilder
编辑:正如Louis Wasserman所指出的那样,它还会为您组合字符串字面量,因此在编译时,上述语句将成为单个字符串。

3
不太正确。如果这些都是字面字符串,编译器会将其优化为单个 String,而不使用 StringBuilder - Louis Wasserman

1

代码:

String str = "aaaaaaa" + "bbbbbbbb" + "cccccccc";

在编译时,gets被转换为:

String str = (new StringBuilder()).append("aaaaaaa").append("bbbbbbbb").append("cccccccc").toString();

因此,使用StringBuilder似乎没有任何区别。

有一篇非常好的文章,详细比较了concat(+)与StringBuilder和StringBuffer的性能,包括线性图表:

StringBuilder vs StringBuffer vs String.concat - Done Right


1
据我所知,JVM内部有一个字符串池,您创建的每个字符串都存储在其中,丢弃最旧/最不常用的字符串(我不确定它如何选择哪些字符串)。如果您显式调用String.intern(),则告诉JVM将字符串放入池中。
当您使用+连接两个字符串时,会在池中产生三个字符串。如果您连接a + b + c,则会产生5个字符串(a,b,ab,c,abc)。
至少在旧版JVM上是这样,但Luiggi很可能是正确的,在新版本上进行了内部优化。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接