Convert string concatenations into StringBuilder or MessageFormat calls with Eclipse’s Quick Fix

Eclipse sports a really nice Quick Fix that turns string concatenations into the recommended calls to StringBuilder. It saves you the time of creating a variable, having to pull out each of the string parts into a call to StringBuilder’s append and then using the string with toString().

So with one key, it will turn code like this:

System.out.println("The year " + year + " is a leap year.");

Into this:

StringBuilder message = new StringBuilder();
message.append("The year ");
message.append(year);
message.append(" is a leap year.");
System.out.println(message.toString());

How to use the Quick Fix

First select the string part that you want to convert. The quickest way is to use the Select Enclosing Element shortcut (Alt+Shift+Up) to quickly select the parts of the string. Then press Ctrl+1 and select Use StringBuilder for string concatenation.

Just to show you how nice this feature is and how much time it can save, here’s a video that converts a 3 part string into 3 calls to a StringBuilder variable called message.

As an added bonus, you can also convert the concatenation into a call to MessageFormat, but only if the concatenation contains a variable part. After you press Ctrl+1 just select Use MessageFormat for string concatenation. The example above should look something like this:

System.out.println(MessageFormat.format("Playing {0} is fun.", soccer));

Related Tips

Support Eclipse On E

12 thoughts on “Convert string concatenations into StringBuilder or MessageFormat calls with Eclipse’s Quick Fix

  1. Great tip, I had a big logger call that printed out some debug information, extracted it from the method using the Extract Method refactoring, and turned it into a neat Formatter call with the MessageFormat quick fix.

    There’s a big piece of HTML that’s being assembled with string concats further on in the code I’m refactoring, so that one’s next. Thanks for the great tips and website.

    • You’re welcome, Cthulhu, and thanks for the compliment. I’m glad the refactoring’s going a bit easier. Good luck with the rest of it.

  2. Actually, the compiler turns String concatenation into StringBuilder calls. The code using StringBuilder explicitly is harder to follow in this simple case.

    public static void main(String[] args) {
    System.out.println(“Hello, ” + args[0] + “, it’s nice to meet you.”);
    }
    becomes:
    public static void main(java.lang.String[] args);
    0 getstatic java.lang.System.out : java.io.PrintStream [16]
    3 new java.lang.StringBuilder [22]
    6 dup
    7 ldc [24]
    9 invokespecial java.lang.StringBuilder(java.lang.String) [26]
    12 aload_0 [args]
    13 iconst_0
    14 aaload
    15 invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [29]
    18 ldc [33]
    20 invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [29]
    23 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [35]
    26 invokevirtual java.io.PrintStream.println(java.lang.String) : void [39]
    29 return

    ps. this is a great blog, keep writing!

    • Interesting bit of info, Kofa, thanks. After reading your comment I found this post that discusses this quite nicely. Seems that the feeling is that concatenations are ok if it’s 2/3 arguments and it’s not in a loop, otherwise use StringBuilder/Buffer.

      I couldn’t figure out if this was compiler-dependant though. Any idea if it applies to all versions of the Sun compiler or to any other vendors’ compilers?

      And thanks for the compliment and encouragement. I appreciate it.

    • I think both the Sun and the Eclipse compiler do this optimisation (I used Eclipse to build the code, that’s where the bytecode comes from).

      BTW, the difference between StringBuffer and StringBuilder performance may go away due to lock elision and escape analysis (synchronisation is removed if it can be proved that the variable can only be accessed by a single thread, e.g. because it’s a local). See the text and links in
      http://www.javaspecialists.eu/archive/Issue179.html

  3. It’s a great idea, but my Eclipse build (20100218-1602, version 3.2 I think) doesn’t handle multiple concatenations very well:

    “Took ” + (b-a) + “ms to perform ” + n + ” iterations: ” + (b-a)/(float)n + “ms per iteration.”

    becomes:

    MessageFormat.format(“{0}ms per iteration.”, “Took ” + (b-a) + “ms to perform ” + n + ” iterations: ” + (b-a)/(float)n)

    It only pulled out the first concatenation, leaving all the others as part of the single parameter {0}.

    Similarly with StringBuilder:

    stringBuilder.append(“Took ” + (b-a) + “ms to perform ” + n + ” iterations: ” + (b-a)/(float)n);
    stringBuilder.append(“ms per iteration.”);

    I’ll update Eclipse and see if this is fixed.

    • Actually it seems like that is the latest Eclipse 3.5.
      I wish the “About” dialogue would display the proper version number, and wish it would update itself between releases… each time I’ve done it in the past, it was by downloading full releases, replacing the old install and messing around to get the workspace and version control settings back. :/

    • I think the version number tends to be there or not depending on the type of package (I might be wrong). I’ve noticed that the Eclipse SDK’s since 3.5 always displays it, but have found that the JEE install may not have it. It is sometimes a nuisance.

      As for upgrading Eclipse, I also go for the complete reinstall route. However, by sharing plugins using links folders and using the File > Export > General > Preferences, it doesn’t take as long to set up the new install.

      And if you want to start with a brand new workspace (ie. not reuse the old one with existing projects), you can also check out how to use team project sets to checkout multiple projects from version control into your workspace.

      I’ll be doing a post soon on how to transfer all types of settings from one workspace to another which makes things a lot easier. So keep an eye out on the blog, especially the category Installation & Setup.

      I know it should be a lot easier than that (eg. one click upgrade), but until Eclipse redesigns things, I’ve found these methods to make the process go a bit smoother.

    • It seems there’s a slight bug in Eclipse 3.5 in handling your expression. However, if you add brackets to the division expression, it seems to work. So if you change your expression to the following, then it works fine:

      “Took ” + (b-a) + “ms to perform ” + n + ” iterations: ” + ((b-a)/(float)n) + “ms per iteration.”

      Notice the extra set of brackets around (b-a)/(float)n.

      I don’t think you need to log a bug though because both versions of your string (with and without the extra brackets) seem to work in Eclipse 3.6, so they seem to have corrected the problem in 3.6.

      Let me know if this works for you.

    • Hello Byron,

      Yes, you’re correct – meant to get back here and correct myself but you did it first! I found the same workaround earlier and posted the bug on the Eclipse tracker, whereupon it was quickly closed since it’s apparently fixed in 3.6 already. Good to know!

      Also many thanks for the tips on keeping my plugins across a re-installation; that’ll be a fun morning tomorrow, especially if it doesn’t destroy all the SVN settings etc (i.e. the password I’ve long forgotten :D).

    • Glad you got it working. And the plugin sharing is definitely worth it – together with preference sharing, it’s brought down my installation time from hours to 5-10 minutes.

  4. Pingback: Eclipse string conversion | Scalable Conversation