In addition to the ReflectionToStringBuilder
, Commons Lang
provides for customization via the ToStringBuilder
and ToStringStyle
class. From the previous recipe, if you only want the
PoliticalCandidate
toString( )
method to print lastName
and firstName
, use the ToStringBuilder
class and pass in a ToStringStyle
object. The following example
demonstrates a toString( )
method
implementation that customizes both style and content:
import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; public String toString( ) { return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) .append("lastName", lastName) .append("firstName", firstName) .toString( ); }
Calling toString( )
on this
object will produce the following output containing only the two
properties specified as parameters to append(
)
:
com.discursive.jccook.lang.builders.customized.PoliticalCandidate@14318bb[ lastName=Jefferson firstName=Thomas ]
Unlike the output shown in Recipe 1.4, this output is shown exactly as it appears on your screen.
Generating toString( )
content
using reflection saves time, but the trade-off is that the code using
reflection prints out every member variable of a given class. What do
you do when the desired behavior is to print out only a few selected
variables from a given class? What if your objects are very wide
, in that they have many properties that
you don't want to print out in a toString()
method? There are situations where
an object could have a large number of properties or when a particular
property of an object might contain a large amount of textual content.
In these situations, it would be counterproductive to use ReflectionToStringBuilder
to print out every
member variable in a class.
Use a ToStringBuilder
and
customize the contents of the output with a static member of a ToStringStyle
. The constructor of a ToStringBuilder
takes an object instance and a
ToStringStyle
, returning an instance
of a ToStringBuilder
. This builder is
then customized by calling append( )
,
which lets you specify the properties you want included in the output.
To customize the contents of a ToStringBuilder
, you must manually add
each property to an instance of a builder. The append( )
method accepts all primitives, objects, and arrays. Table 1-1 summarizes the variations of
append( )
for integer primitives and
objects.
Table 1-1. Variations of ToStringBuilder append( )
ToStringBuilder method |
Description |
---|---|
|
Appends the value of the integer. |
|
Appends the value of the integer and the name of the property. |
|
Appends the |
|
Appends the |
|
Appends the formatted contents of array. |
|
Appends the property name and the size of an array |
|
Appends the property name and the full contents of an array. |
The ToStringStyle
class
provides a mechanism to customize the output of a ToStringBuilder
, and this class contains a few
built-in styles. One example is the ToStringStyle.MULTI_LINE_STYLE
, which puts a
newline character between every property. Another example is the
ToStringStyle.SIMPLE_STYLE
, which
simply prints the value of every member variable. The following list
provides an example of each of these preset styles:
ToStringStyle.DEFAULT_STYLE
com.discursive.jccook.lang.builders. PoliticalCandidate@1cd2e5f[lastName=Jefferson,firstName=Thomas]
ToStringStyle.MULTI_LINE_STYLE
com.discursive.jccook.lang.builders.PoliticalCandidate@1cd2e5f[ lastName=Jefferson firstName=Thomas ]
ToStringStyle.NO_FIELD_NAMES_STYLE
com.discursive.jccook.lang.builders.PoliticalCandidate@1cd2e5f[Jefferson,Thomas]
ToStringStyle.SIMPLE_STYLE
Jefferson,Thomas
What's the big deal about toString()
methods? This is about accuracy and
keeping messages relevant in an evolving system. All useful error
messages include a string representation of the object involved in the
error. If you get an exception, and you print the value of an object, it
is usually clear what is causing that exception. In the absence of
sensible logging, it is next to impossible to debug a system without
diving directly into a debugger. This is especially true if you are
trying to diagnose the cause of an infrequent problem that only affects
a tiny percentage of users who only encounter a problem if they perform
a very specific action in a specific context. In these cases, it is
helpful to know the internal state of every object involved in the
error, and toString( )
is the easiest
way to print this out to a log. Automate your toString( )
method, and your error messages
will be more meaningful.