The costs of String concatenation (+) or what String appending really does

String concatenation (e.g. “fu” + “bar”) are for most developers a mystery what it really does.

The simple case
Something like

System.out.println("fu" + "bar");

will usually be appended at compile time.

So if you decompile this you see:

System.out.println("fubar");

The final case
What happens if an primitive final variable comes into place?

        final int i = 5;
        System.out.println("fu" + i+ "bar"); 

Results into (eclipse Compiler):

        int i = 5;
        System.out.println("fu5bar");

Sun Compiler

        System.out.println("fu5bar");

In the remaining cases

        int i = 5;
        System.out.println("fu" + i+ "bar"); 

Results into (eclipse compiler)

        int i = 5;
        System.out.println((new StringBuilder("fu")).append(i).append("bar").toString());

or into (sun jdk compiler)

        byte byte0 = 5;
        System.out.println((new StringBuilder()).append("fu").append(byte0).append("bar").toString());

We see, that if the result of the appending (I hate that other word) is only a bit unknown at compile time, it uses a new StringBuilder to create a new String.

No goes for String appending
Conversion of something into a String.

        int i = 5;
        String iString = "" + i;
        System.out.println(iString);

Will create a StringBuilder for converting a int into a String. You have to use the String.valueOf() or the toString method.

Using appending in a loop

String s = "";
for (int i=0; i < 10; i++) {
   s += i; 
}

This will create a StringBuilder and a String in each loop cycle. You can locate such usage easily with FindBugs. You should manually create a StringBuilder.

Conclusion
For nearly each creation of a String with the common append (+) method a StringBuilder is created.
Creating an Object(here StringBuilder) is expensive, but not so expensive to change the style.
It is important not to use String appending in a loop. Thats a real performance issue.

That’s why something like this, will create 2 StringBuilder. Therefore it is important to append all necessary data in one Statement, otherwise a manual created StringBuilder may be needed.

        System.out.println("fu" + i+ "bar");
        System.out.println(i + "blub");

For logging exists following idiom, which has to be used for most Loggers.

if (logger.isInfoEnabled()) {
     logger.info("fu" + i + "bar");
}

Because only if info is enabled, a new StringBuilder and String has to be created. On the other hand, if info is enabled the check that info is enabled have to be done twice. One time in our if and the other time in logger.info().

But there exists other approaches. For example the Logger framework SL4J and the various implementations like logback. They use parametrized logging.

logger.debug("The new entry is {}. It replaces {}.", entry, oldEntry);

(All decompiled code was previously compiled with eclipse compiler 3.5 and sun JDK compiler Java6u18).

This entry was posted in common practice, Formatting, Java, Performance and tagged , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *