A fixed literal like in your example is more efficient than using a StringBuilder.
The fixed literal will be detected by the compiler and will be inlined as a single value, so the two lines
String s = "one" + "two" + "three";
and
String s = "onetwothree";
will generate exactly the same bytecode.
The picture is different though if the concatenation is not done with literals but with function calls.
When you need to append strings dynamically, prefer StringBuilder over StringBuffer because it is slightly faster as it is not synchronized.
Here is the example bytecode:
public class Test
{
private String s = "one" + "two" + "three";
}
public class Test2
{
private String s2 = "onetwothree";
}
the generated bytecode for these classes is:
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
}
As you can see both variables are treated the same way.
I don't think this belongs to the language specification, as this is "just" a compiler optimization.
A different compiler (I was using the Sun compiler) might be doing something completely different - which is OK as long as the behaviour doesn't change.