Code style determines how the generated method works and what classes it uses. There are several code styles available to chose from the combo box in generator's dialog:
return "FooClass [aFloat=" + aFloat + ", aString=" + aString + ", anInt=" + anInt + ", anObject=" + anObject + "]";With "Skip null values" option turned on, the code becomes a little harder to read:
return "FooClass [aFloat=" + aFloat + ", " + (aString != null ? "aString=" + aString + ", " : "") + "anInt=" + anInt + ", " + (anObject != null ? "anObject=" + anObject : "") + "]";
StringBuilder builder = new StringBuilder(); builder.append("FooClass [aFloat="); builder.append(aFloat); builder.append(", aString="); builder.append(aString); builder.append(", anInt="); builder.append(anInt); builder.append(", anObject="); builder.append(anObject); builder.append("]"); return builder.toString();The "Skip null values" option doesn't obfuscate the code as much as previously:
StringBuilder builder = new StringBuilder(); builder.append("FooClass [aFloat="); builder.append(aFloat); builder.append(", "); if (aString != null) { builder.append("aString="); builder.append(aString); builder.append(", "); } builder.append("anInt="); builder.append(anInt); builder.append(", "); if (anObject != null) { builder.append("anObject="); builder.append(anObject); } builder.append("]"); return builder.toString();
StringBuilder builder = new StringBuilder(); builder.append("FooClass [aFloat=").append(aFloat).append(", aString=").append(aString) .append(", anInt=").append(anInt).append(", anObject=").append(anObject).append("]"); return builder.toString();With "Skip null values" switched on, the chain must be broken:
StringBuilder builder = new StringBuilder(); builder.append("FooClass [aFloat=").append(aFloat).append(", "); if (aString != null) { builder.append("aString=").append(aString).append(", "); } builder.append("anInt=").append(anInt).append(", "); if (anObject != null) { builder.append("anObject=").append(anObject); } builder.append("]"); return builder.toString();
return String.format("FooClass [aFloat=%s, aString=%s, anInt=%s, anObject=%s]", aFloat, aString, anInt, anObject);Because there's no
String.format()
in JDK 1.4 and earlier, MessageFormat.format()
is used instead:
return MessageFormat.format("FooClass [aFloat={0}, aString={1}, anInt={2}, anObject={3}]", new Object[] { new Float(aFloat), aString, new Integer(anInt), anObject });
This style uses an external class to build a result string. It can use classes that fulfill the following conditions:
Object
as parameter - it will be passed an object for which the toString() method is calledObject
and (optionally) a String
(in any order)String
Custom builder requires some additional configuration to work properly. All necessary options can be entered in a dialog box showing up after clicking 'Configure...' button. These options include:
String
) are preferred over those taking a single argument (additionally, the String
argument shall preferably be the first one). If there are versions of the method that take specific argument types, they are also used when possible.For example, suppose your builder class looks like this:
package org.foo.ToStringBuilder2; public class ToStringBuilder2 { public ToStringBuilder2(Object o) {...} public ToStringBuilder2 appendItem(String s, Object o) {...} public ToStringBuilder2 appendItem(String s, float f) {...} public String getString() {...} }
Of course in this case builder class should be set to "org.foo.ToStringBuilder2"
, builder label can be for example "builder"
, append method is "appendItem"
and result method is "getString"
. With chain invocations selected, generated method will look like this:
ToStringBuilder2 builder = new ToStringBuilder2(this); builder.append("aFloat", aFloat).append("aString", aString).append("anInt", new Integer(anInt)) .append("anObject", anObject); return builder.getString();
Note that a primitive variable anInt
was passed to the builder using wrapper type. This is done for projects using JDK 1.4 and earlier (for later JDKs the compiler does it automatically). In case of aFloat
there was a specific method in builder class so no wrapping was required.