There are lots of myths around concatenating Strings in Java. Lets find out exactly which of them are true.
The results are based on the Oracle JDK 1.7 (Update 3). Please, feel free to leave a comment, if the compiler you are using works differently.
Myth 1: You should always use StringBuilder when concatenating Strings
When arguing about whether to use StringBuffer or StringBuilder it is usually fair to say that StringBuilder is better, because the StringBuffer has all the methods synchronized which can harm the performance. However, it is not always true that you have to use StringBuilder:
The most obvious case is concatenating final values. Joining the standard Java constants:
...will be optimized by the compiler to:
What may be surprising, the final on its own is sufficient, so this snippet:
...will be optimized to:
The bytecode behind looks like this:
What about the non-final fields? You should be a little bit concerned why do you want this, but leaving the rest to the compiler is also OK. Although the non-final fields are not optimized straight into Strings, StringBuilder is used. The following code for example:
...will be transformed by the compiler into this:
The bytecode for the intrigued:
How about concatenating arguments of different types inside a method? Leave it to the compiler. This piece of code:
...will be turned into this:
The bytecode:
Myth 2: You can rely on the StringBuilder optimization when you are concatenating inside an if statement
After reading some Java compiler specs you can fall for this. Unfortunately this is not true. Whenever you are concatenating Strings in more than one expression, you should watch out. For example this:
...will be unfortunately "optimized" to this code:
...when we expected this code:
Again the bytecode for the comparison with the decompiled Java code:
Going further, the "advanced" example with an if statement will work out no better. The following:
...will NOT be magically turned into this:
Instead it will come down to this:
As an exercise you can check the bytecode yourself.
To generate the bytecode you have to first compile your java class:
Then disassemble the class file:
As a result the bytecode will be saved to the bytecode.txt file.
Myth 3: StringBuilder should be used only if you are concatenating inside a loop
This myth is based on the assumption that the compiler is so clever that it can guess correctly where and how to put StringBuilder for the most of the time. After reading up to this point you should already know it is not true. StringBuilder should be used much more than expected. However, joining Strings inside a loop is a special case, where you can be 100% sure you have to use StringBuilder (or StringBuffer on rare occasions). For instance this:
...equals this:
...and we really wanted this:
Summary
I hope you enjoyed the article. Please, leave a comment, if you think there is something that should be added to the topic.
TL;DR: For the most cases use the StringBuilder class. Better be safe than sorry.
UPDATE:
TL;DR (made by standardout in the comments): As a general rule, use '+' operator String concatenation when everything is defined in a single line. In some cases it will be more efficient, but even when not it will at least be easier to read. But never use += with Strings.
If you want to learn more, you can follow the Reddit discussion about this blog post (as Javin Paul suggested).