views:

549

answers:

1

Suppose I have an expression in Java such as:

String s = "abc" + methodReturningAString() + "ghi" + 
                anotherMethodReturningAString() + "omn" + "blablabla";

What's the behaviour of the Java's default JDK compiler? Does it just makes the five concatenations or there is a smart performance trick done?

+17  A: 

It generates the equivalent of:

String s = new StringBuilder("abc")
           .append(methodReturningAString())
           .append("ghi")
           .append(anotherMethodReturningAString())
           .append("omn")
           .append("blablabla")
           .toString();

It is smart enough to pre-concatenate static strings (i.e. the "omn" + "blablabla"). You could call the use of StringBuilder a "performance trick" if you want. It is definitely better for performance than doing five concatenations resulting in four unnecessary temporary strings. Also, use of StringBuilder was a performance improvement in (I think) Java 5; prior to that, StringBuffer was used.

Edit: as pointed out in the comments, static strings are only pre-concatenated if they are at the beginning of the concatenation. Doing otherwise would break order-of-operations (although in this case I think Sun could justify it). So given this:

String s = "abc" + "def" + foo() + "uvw" + "xyz";

it would be compiled like this:

String s = new StringBuilder("abcdef")
           .append(foo())
           .append("uvw")
           .append("xyz")
           .toString();
Kip
+1. I saw the StringBuilder and was all set to post a clarification until I got to the bottom and found you'd already taken care of it.
Michael Myers
yep, i couldn't remember which one was correct, had to look it up after my initial revision
Kip
Actually, I was referring to the concatenation of string literals. At first glance, I thought you'd used a `.append` for each string.
Michael Myers
that's the second time on SO today that i misread someone's comment and responded to it... i must be getting old or something
Kip
@Kip: Not to be contrary, but I compiled the code with Sun's javac 1.6.0_15 and ran the .class through jad (and javap) and it actually compiled to: `String s = (new StringBuilder()). append("abc"). append(methodReturningAString()). append("ghi"). append(anotherMethodReturningAString()). append("omn"). append("blablabla"). toString();` It looks like the Sun compiler isn't smart enough to pre-concatenate static strings in this case.
Grant Wagner
@Kip: I compiled the same code using the compiler built into IBM RAD (based on Eclipse) and it compiled to: `String s = (new StringBuilder("abc")). append(methodReturningAString()). append("ghi"). append(anotherMethodReturningAString()). append("omn"). append("blablabla"). toString();` which still misses the literal string optimization, but at least creates the `StringBuilder` with the first `append()`able String.
Grant Wagner
It's not about being smart or not. The Java language specification has very specific rules about the order of evaluation, namely that it must be left-to-right when the operators are all of the same precedence. So, although "foo" + "bar" + baz does become new StringBuilder("foobar").append(baz), foo + "bar" + "baz" cannot be compiled into new StringBuilder().append(foo).append("barbaz") without breaking the order-of-evaluation rule.
Chris Jester-Young
@Chris: So the answer, as presented, is wrong.
Grant Wagner
@Chris Jester-Young: @Grant Wagner: I've updated the answer with your feedback. At one point I'm pretty sure it used to create the StringBuilder object with the default (no-param) constructor, but I guess it doesn't any more
Kip
Well, I've learned something new today!
Michael Myers
@Chris, that is true, but it can also be shown pre-compile that the order of evaluation does not change the result, so the optimization would be allowable.
280Z28