0

From the below 3 different implementations, which one looks like a good candidate based on readability, performance, etc?

Example#1:

@Override
public String toString() {
    return "GuiTemplateCriteriaImpl [appTitle=" + appTitle
            + ", button1Text=" + button1Text + ", button2Text="
            + button2Text + ", defaultMessageText=" + defaultMessageText
            + ", rootFolder=" + rootFolder + ", supportedFileExt="
            + supportedFileExt + ", list1ToolTipText=" + list1ToolTipText
            + ", list2ToolTipText=" + list2ToolTipText + "]";
}

Example#2:

@Override
public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("GuiTemplateCriteriaImpl")
           .append("[")
           .append("  appTitle="    + appTitle)
           .append(", button1Text=" + button1Text)
           .append(", button2Text=" + button2Text)
           .append(", defaultMessageText=" + defaultMessageText)
           .append(", rootFolder="  + rootFolder)
           .append(", supportedFileExt=" + supportedFileExt)
           .append(", list1ToolTipText=" + list1ToolTipText)
           .append(", list2ToolTipText=" + list2ToolTipText)
           .append("]");
    return builder.toString();
}

Example#3:

@Override
public String toString() {
    return new StringBuilder()
           .append("GuiTemplateCriteriaImpl")
           .append("[")
           .append("  appTitle="    + appTitle)
           .append(", button1Text=" + button1Text)
           .append(", button2Text=" + button2Text)
           .append(", defaultMessageText=" + defaultMessageText)
           .append(", rootFolder="  + rootFolder)
           .append(", supportedFileExt=" + supportedFileExt)
           .append(", list1ToolTipText=" + list1ToolTipText)
           .append(", list2ToolTipText=" + list2ToolTipText)
           .append("]")
           .toString();
}

Any other best practices around this method? Please advise

Thanks!

Rookie
  • 5,179
  • 13
  • 41
  • 65
  • A very similar question: http://stackoverflow.com/questions/1532461/stringbuilder-vs-string-concatenation-in-tostring-in-java – Mike Zboray May 25 '15 at 18:39
  • Usually the reason to use `StringBuilder` is to remove all `+` operator concatenations for performance reasons, however examples 2 & 3 don't do that. You've still got `+` in the arguments, which is arguably going to be worse than Example 1, depending on how the compiler optimizes it. – Mike Zboray May 25 '15 at 20:21
  • so does that mean that if we remove the + from example#2, it will actually perform better than Ex#1? What is the reasoning behind it if i may know..Some others say here that they both compile to the same bytecode although Ex#2 has slightly higher overhead – Rookie May 25 '15 at 21:21
  • 1
    No it would likely perform the same. Many have pointed to the JLS section noting that the compiler is permitted to transform + into a series of StringBuilder operations. If it is doing that then in all likelihood there is one StringBuilder created in #1, but in the others one is created for each expression that contains +, which is 8 in addition to the one you explicitly allocated. – Mike Zboray May 25 '15 at 21:33
  • Thanks for clarifying that for me Mike. Really appreciated! – Rookie May 25 '15 at 21:35
  • Honestly, all these arguments about perf are speculative at best. To borrow an analogy, if you want to know which of two horses is faster, you race them. You don't show pictures to random people on the internet and ask them to guess. If you want to know which code is faster, you benchmark it in a realistic environment for a scenario that is relevant to users. You don't post it to Stack Overflow and ask people to guess. – Mike Zboray May 25 '15 at 21:38
  • thanks but being new to it, getting information from people more knowledgeable than me gives insight into facts i am unaware of, so posted out on SO. And knowing why one method is faster than the other than just benchmarking will add more value to learning. – Rookie May 25 '15 at 21:59

3 Answers3

5

Example 1 will use a single StringBuilder behind the scenes for you. Example 2 and 3 will compile to the same bytecode but using more StringBuilders, one per string concatenation when using non-literal Strings, but the overhead for this case can be ignored. Use the one that eases code readability and maintainability for your specific case.

IMO you should use option #4:

@Override
public String toString() {
    return "GuiTemplateCriteriaImpl"
        + "["
        +" appTitle=" + appTitle
        + ", button1Text=" + button1Text
        + ", button2Text=" + button2Text
        + ", defaultMessageText=" + defaultMessageText
        + ", rootFolder=" + rootFolder
        + ", supportedFileExt=" + supportedFileExt
        + ", list1ToolTipText=" + list1ToolTipText
        + ", list2ToolTipText=" + list2ToolTipText
        + "]";
}
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • so no performance impact by using new StringBuilder() instead of just a new String()? – Rookie May 25 '15 at 16:00
  • You sure - can the compiler collapse the `String` concat in the existing`StringBuilder`? – Boris the Spider May 25 '15 at 16:00
  • @Rookie where have you used `new String`? – Boris the Spider May 25 '15 at 16:00
  • i meant just returning a string "sample string", sorry – Rookie May 25 '15 at 16:01
  • `Example 1 will use a single StringBuilder`. Could you please point me to a solid source that says that the first case will always use a `StringBuilder`? – Chetan Kinger May 25 '15 at 16:16
  • Well, I just use `javap -c Compiled.class` on this and I can see the usage of `StringBuilder` for this long string, since JDK 6 HotSpot. If that's not solid for you, then I don't know what will be. – Luiggi Mendoza May 25 '15 at 16:19
  • @Luggi That's not solid for me. It needs to be documented somewhere for it to be solid. The bible of Java documents ([JLS](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.18.1)) also says that the java compiler `may` optimize in case of the first case. Are you saying that the JLS is wrong? – Chetan Kinger May 25 '15 at 16:34
  • I'm saying that HotSpot implementation is not wrong and does this for you. If you use a different implementation than OpenJDK or HotSpot, check how the string concatenation is implemented by using `javap -c YourClass.class`. – Luiggi Mendoza May 25 '15 at 16:36
1

I would use option #1. Options #2 and #3 create a new StringBuilder each time you use + concatenation on a string. That's not a lot of overhead, but it could add up, since you're creating a new object and throwing it away each time. Option #1 only creates one StringBuilder, since it's just one big long concatenation.

You can just reformat option #1 so it looks a bit nicer.

@Override
public String toString() {
    return "GuiTemplateCriteriaImpl ["
            + "appTitle=" + appTitle
            + ", button1Text=" + button1Text
            + ", button2Text=" + button2Text 
            + ", defaultMessageText=" + defaultMessageText
            + ", rootFolder=" + rootFolder 
            + ", supportedFileExt=" + supportedFileExt 
            + ", list1ToolTipText=" + list1ToolTipText
            + ", list2ToolTipText=" + list2ToolTipText + "]";
}
markspace
  • 10,621
  • 3
  • 25
  • 39
1

Just as a side-note:

If you don't mind using a 3rd party library, then you could also check out the ToStringBuilder in Apache Commons Lang3: http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/ToStringBuilder.html

It allows some customizations of the output format (using a predefined implementation or self-implemented ToStringStyle).

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
jCoder
  • 2,289
  • 23
  • 22
  • any particular benefits by adding an extra dependency on this class? – Rookie May 25 '15 at 16:11
  • Despite the fact that Commons Lang3 also contains other useful classes (e.g. `HashCodeBuilder` or `EqualsBuilder` for similar purposes as the `ToStringBuilder`) the toString() output can be customized and I guess it provides a proven and performant implementation. – jCoder May 25 '15 at 18:11