1.5. Customizing Generated toString( ) Content

Problem

You need to automate toString( ) while retaining control over the output, contents, and formatting.

Solution

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.PoliticalCandidate@1cd2e5f[
  lastName=Jefferson
  firstName=Thomas
]

Tip

Unlike the output shown in Recipe 1.4, this output is shown exactly as it appears on your screen.

Discussion

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

append(int value)

Appends the value of the integer.

append(String n, int value)

Appends the value of the integer and the name of the property.

append(Object value)

Appends the toString( ) of an Object.

append(String n, Object value)

Appends the toString( ) of an Object and the name of the property.

append(int[] array)append(Object[] array)

Appends the formatted contents of array.

append(String n int[] array)append(String n, Object[] array)

Appends the property name and the size of an array

append(String n, int[] array, boolean detail)

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.

Get Jakarta Commons Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.