Фиксированный литерал, как в вашем примере, более эффективен, чем использование StringBuilder.
Фиксированный литерал будет обнаружен компилятором и будет встроен как одно значение, поэтому две строки
String s = "one" + "two" + "three";
и
String s = "onetwothree";
сгенерируют точнотот же байт-код.
Изображение отличается, хотя, если конкатенация выполняется не с литералами, а с вызовами функций.
Когда вам нужно динамически добавлять строки, предпочтите StringBuilder, а не StringBuffer, поскольку он немногобыстрее как то не синхронизируется.
Вот пример байт-кода:
public class Test
{
private String s = "one" + "two" + "three";
}
public class Test2
{
private String s2 = "onetwothree";
}
сгенерированный байт-код для этих классов:
c:\Temp>javap -c Test
Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: aload_0
5: ldc #2; //String onetwothree
7: putfield #3; //Field s:Ljava/lang/String;
10: return
}
c:\Temp>javap -c Test2
Compiled from "Test2.java"
public class Test2 extends java.lang.Object{
public Test2();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: aload_0
5: ldc #2; //String onetwothree
7: putfield #3; //Field s:Ljava/lang/String;
10: return
}
Как видите, обе переменные обрабатываются одинаково.
Я не думаю, что это относится к языковой спецификации, поскольку это «просто» оптимизация компилятора.
Другой компилятор (я использовал компилятор Sun) может делать что-то совершенно другое - это нормально, пока поведение не меняется.