Update:
A friend of mine read this blog entry and showed me some decompiled Java where the compiler actually replaced the + operator. I played around with some Java compilation/decompilation and it seems that the compiler replaces the + operator with either StringBuilder or creating a new static String (e.g. “JavaDeus ” + 2008 would be compiled to “JavaDeus 2008″. Some examples can be found here. Jad files can be viewed with any text editor.
First, I have to say I don’t give performance tests much attention. However, at CS 101 I learned that using the +operator in Java to build Strings is evil. It is not only evil, it’s also a sign of noobism. At my current job, we use the + operator all over in the code. When I first saw it, I asked my colleagues if doing that doesn’t hurt the performance and memory consumption. They replied that some tests showed that there is no real difference to using StringBuilder for example, except that using StringBuilder is more work. I had read some articles about String performance, and I knew that the compiler does some optimizations, but I wasn’t fully convinced. So I did my own ‘professional’ tests, and the result was: it doesn’t matter. Hence, I settled the issue and forgot it. Yesterday, a friend of mine was complaining about Java and its String handling. Since I am Java enthusiast, I thought not Java is the problem, probably its your code. Then I saw it again, the + operator!
Typical, noob mistake, isn’t it? Hence, I told him about StringBuilder and about the evil + operator. I also created a small test to show him (or me off ;)) the difference. And the results were phenomenal! + operator was about 50 % slower than StringBuilder. With the new gained confidence in StringBuilder, I showed the results to one colleague. After a short review, he pointed out a mistake in my test. After correcting the mistake, the results were … mixed. Actually, the results showed no clear winner (+ operator is maybe a little bit faster). But I didn’t want to give up so fast, so I tested the memory consumption (String memory handling is different). Again, no difference. I added StringBuffer and String.format to the test. String.format is the slowest, which is not a surprise, and StringBuffer is slightly slower than StringBuilder and the + operator.
My conclusion is: it doesn’t matter. Use whatever you want, there is actually no real difference. But, I challenge you to convince me otherwise

Daniel responded on 28 Jun 2008 at 12:03 pm #
String concatenation isn’t bad for constant string construction (s = a + b + c) since javac decomposes it to StringBuilder calls anyway, but it totally blows for incremental output in loops because it creates an entirely new String on every iteration. This leads to exponential performance degradation, which you absolutely don’t want for this simple task. Test
final int count = 30000;
String s = “”;
for (int i = 0; i < count; i++) {
s += ‘ ‘;
}
versus
final StringBuilder builder = new StringBuilder();
for (int i = 0; i < count; i++) {
builder.append(’ ‘);
}
builder.toString()
The latter takes almost no time, while the former creates a serious performance (and memory) bottleneck.
heli responded on 29 Jun 2008 at 10:02 pm #
Thanks Daniel for your note. You are right, the first code example:
final int count = 30000;
String s = “”;
for (int i = 0; i < count; i++) {
s += ‘ ‘;
}
will be compiled to:
int count = 30000;
String s = “”;
for(int i = 0; i < 30000; i++)
s = (new StringBuilder()).append(s).append(’ ‘).toString();
Actually, I was surprised by this result. I thought the compiler is more clever and would create a StringBuilder outside the loop and then assign it to the String at the end of the loop. I find the compiled result pretty awkward because it doesn’t really improve anything, it probably makes the result worse? (because now a StringBuilder and a new String has to be created and some methods are called.
Daniel responded on 30 Jun 2008 at 10:54 am #
Since String is immutable, the only way of appending something to a String is through an external builder class like StringBuilder. This wouldn’t be even that bad for performance, but the StringBuilder has to put the existing String into its internal buffer first - this leads to non-linear performance.
Note that this isn’t really a Java issue, it’s an effect of having immutable Strings and affects many other languages as well (e.g. Python).
heli responded on 30 Jun 2008 at 12:20 pm #
I consider immutable Strings a good thing and I know what you are trying to say, but my objection is:
the compiled code should be:
int count = 30000;
String s =
Daniel responded on 30 Jun 2008 at 9:53 pm #
I’m no compiler expert, but I guess that such an optimization (that actually modifies the semantics of the generated code) is very hard to do right if it should be useful for more than micro-benchmarks than the above code snippet.
Regarding finals and inlining: I think that this is done mostly by Hotspot (the JIT compiler). Check out this post:
http://weblogs.java.net/blog/kohsuke/archive/2008/03/deep_dive_into.html
It’s all pretty complicated, but it seems that there’s a lot going on below the bytecode level.
heli responded on 01 Jul 2008 at 9:02 am #
Thanks for the link and the interesting discussion. In the deep dive into post I also found another interesting one http://blog.xebia.com/2007/12/21/did-escape-analysis-escape-from-java-6/
It sure looks like there is a lot of optimization going on at the bytecode level.
sycleillinee responded on 03 Aug 2008 at 9:43 am #
I agreed with you