当Java Compiler在一行中看到许多String连接时会发生什么?

Gui*_*rme 30 java string performance concatenation

假设我在Java中有一个表达式,例如:

String s = "abc" + methodReturningAString() + "ghi" + 
                anotherMethodReturningAString() + "omn" + "blablabla";
Run Code Online (Sandbox Code Playgroud)

Java的默认JDK编译器的行为是什么?它只是制作五个连接还是有智能性能技巧?

Kip*_*Kip 40

它产生相当于:

String s = new StringBuilder("abc")
           .append(methodReturningAString())
           .append("ghi")
           .append(anotherMethodReturningAString())
           .append("omn")
           .append("blablabla")
           .toString();
Run Code Online (Sandbox Code Playgroud)

它足够聪明,可以预先连接静态字符串(即"omn" + "blablabla").StringBuilder如果你愿意,你可以使用"性能技巧".性能肯定比做五个连接更好,导致四个不必要的临时字符串.另外,使用StringBuilder是(我认为)Java 5中的性能改进; 在此之前,使用了StringBuffer.

编辑:正如注释中所指出的,如果静态字符串位于连接的开头,则它们仅被预先连接.否则会破坏运营顺序(尽管在这种情况下我认为Sun可以证明这一点).所以这个:

String s = "abc" + "def" + foo() + "uvw" + "xyz";
Run Code Online (Sandbox Code Playgroud)

它会像这样编译:

String s = new StringBuilder("abcdef")
           .append(foo())
           .append("uvw")
           .append("xyz")
           .toString();
Run Code Online (Sandbox Code Playgroud)

  • 这不是关于聪明与否.Java语言规范对评估顺序有非常具体的规则,即当运算符具有相同的优先级时,它必须是从左到右.所以,虽然"foo"+"bar"+ baz确实成为新的StringBuilder("foobar").append(baz),foo +"bar"+"baz"无法编译成新的StringBuilder().append(foo).追加("barbaz")而不破坏评估顺序规则. (3认同)