Is that a recent change? I seem to recall seeing
something more like
String s = (new StringBuilder())
.append(hello).append(world).toString();
... which is closer to Roedy's description. (Of course, in
Days Of Yore it was StringBuffer instead of StringBuilder.)
Here are three decompilations with Javap from JDK 1.6.0_07 which
should settle the matter. The important point is concatenation makes
no attempt to optimise the size of the StringBuilder, even for the
simplest cases.
Showing building a String with StringBuilder.
final StringBuilder sb = new StringBuilder( 1024 );
sb.append( "<table class=\"borderless\" summary=\"" );
sb.append( title );
sb.append( " art print\"><tbody>\n" );
11: new #13; //class java/lang/StringBuilder
14: dup
15: sipush 1024
18: invokespecial #14; //Method
java/lang/StringBuilder."<init>"
I)V
21: astore 6
23: aload 6
25: ldc #15; //String <table class=\"borderless\" summary=\"
27: invokevirtual #16; //Method
java/lang/StringBuilder.append
Ljava/lang/String
Ljava/lang/StringBuilder;
30: pop
31: aload 6
33: aload_1
34: invokevirtual #16; //Method
java/lang/StringBuilder.append
Ljava/lang/String
Ljava/lang/StringBuilder;
37: pop
38: aload 6
40: ldc #17; //String art print\"><tbody>\n
42: invokevirtual #16; //Method
java/lang/StringBuilder.append
Ljava/lang/String
Ljava/lang/StringBuilder;
-------------------------------
two literals with concatenation, and no estimate for StringBuilder
size.
return "PostScript " + "(¡
exclamdown";
// combined at compile time
1326: ldc #89; //String PostScript (¡
exclamdown
1328: areturn
-------------------------------------------
concatenation involving literals, variables and constants:
return "needs Java " + version + " or later, version " +
JRE_FULL_VERSION + " recommended";
creates a StringBuilder with default size.
Note that even though JRE_FULL_VERSION is a public static final
String, the concatenations of literas before and after are NOT done at
compile time.
9: new #17; //class java/lang/StringBuilder
12: dup
13: invokespecial #18; //Method
java/lang/StringBuilder."<init>"
)V
16: ldc #19; //String needs Java
18: invokevirtual #20; //Method
java/lang/StringBuilder.append
Ljava/lang/String
Ljava/lang/StringBuilder;
21: aload_0 [ version is a parm passed to this method ]
22: invokevirtual #20; //Method
java/lang/StringBuilder.append
Ljava/lang/String
Ljava/lang/StringBuilder;
25: ldc #21; //String or later, version
27: invokevirtual #20; //Method
java/lang/StringBuilder.append
Ljava/lang/String
Ljava/lang/StringBuilder;
30: getstatic #22; //Field
com/mindprod/htmlmacros/SunJDKandJREVersions.JRE_FULL_VERSION:Ljava/lang/String;
33: invokevirtual #20; //Method
java/lang/StringBuilder.append
Ljava/lang/String
Ljava/lang/StringBuilder;
36: ldc #23; //String recommended
38: invokevirtual #20; //Method
java/lang/StringBuilder.append
Ljava/lang/String
Ljava/lang/StringBuilder;
41: invokevirtual #24; //Method
java/lang/StringBuilder.toString
)Ljava/lang/String;
44: areturn
The append method chosen returns a pointer to the StringBuilder, so
you don't have to manually dup it at each stage. invokeVirtual
consumes it..
so I would say that:
return "needs Java " + version + " or later, version " +
JRE_FULL_VERSION + " recommended";
compiles effectively to:
StringBuilder temp = new StringBuilder( /* default size */ );
// temp in on stack, not stack frame.
return temp.append( "needs Java " )
..append ( version )
..append ( " or later, version " )
..append( JRE_FULL_VERSION )
..append( " recommended")
..toString();