Use the Commons Lang ReflectionToStringBuilder
or ToStringBuilder
and ToStringBuilder
to create toString()
methods. The following code is an
example of a toString( )
method,
which uses a reflection builder:
import org.apache.commons.lang.builder.ReflectionToStringBuilder; public String toString() { return ReflectionToStringBuilder.reflectionToString(this); }
Assume that you have an object named PoliticalCandidate
—a bean that represents some
information about a presidential candidate. This bean has a set of
properties: firstName
, lastName
, dateOfBirth
, moneyRaised
, and homeState
. Example
1-1 shows the PoliticalCandidate
class using a ReflectionToStringBuilder
; the getter and
setter methods have been omitted for brevity.
Example 1-1. The PoliticalCandidate class using ReflectionToStringBuilder
import java.math.BigDecimal; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; // START lang_tostring_solution import org.apache.commons.lang.builder.ReflectionToStringBuilder; // OMIT lang_tostring_solution import com.discursive.jccook.lang.builders.State; public class PoliticalCandidate { private String lastName; private String firstName; private Date dateOfBirth; private BigDecimal moneyRaised; private State state; public PoliticalCandidate() { } public PoliticalCandidate(String lastName, String firstName, Date dateOfBirth, BigDecimal moneyRaised, State state) { this.lastName = lastName; this.firstName = firstName; this.dateOfBirth = dateOfBirth; this.moneyRaised = moneyRaised; this.state = state; } // get/set methods are omitted for brevity... // END OMIT lang_tostring_solution public String toString() { return ReflectionToStringBuilder.reflectionToString(this); } // END lang_tostring_solution }
The process of keeping the contents of a toString()
method synchronized with a changing
object model becomes a chore (usually a forgotten one). Commons Lang
includes a fairly simple utility designed to automate this chore using
reflection. The ToStringBuilder
class and its extension, ReflectionToStringBuilder
, can condense a large toString(
)
method body into one line of code. Most importantly, the
ReflectionToStringBuilder
reflects
any future changes that are made to the object model. The following code
demonstrates the output of a string built via reflection:
// Create a State State va = new State("VA", "Virginia"); // Create a Birth Date Calendar calendar = new GregorianCalendar(); calendar.set(Calendar.YEAR, 1743); calendar.set(Calendar.MONTH, Calendar.APRIL); calendar.set(Calendar.DAY_OF_MONTH, 13); Date dob = calendar.getTime(); BigDecimal moneyRaised = new BigDecimal(293829292.93); // Create a Political Candidate PoliticalCandidate candidate = new PoliticalCandidate("Jefferson", "Thomas", dob, moneyRaised, va); System.out.println(candidate);
Assume that the State
object is
another bean using the same ReflectionToStringBuilder
. The code above sets
the properties of a bean and produces the following output:
com.discursive.jccook.lang.builders.reflect.PoliticalCandidate@ca0b6[lastName=Jefferson,firstName=Th omas,dateOfBirth=Sat Apr 13 00:54:12 EST 1743,moneyRaised=293829292.930000007152557373046875,state=c om.discursive.jccook.lang.builders.State@69b332[abbreviation=VA,name=Virginia]]
As in other cases in this book, I've applied a minimal amount of formatting to the output so that it fits on the printed page. Your results will be the same in terms of content but will be all on one long line.
This is not the most readable piece of information in the world,
but it was automatically generated. Keeping a
toString( )
method up-to-date in an
object model that contains one hundred entities is next to impossible
under the constraints of a deadline and a budget. If your objects have
meaningful toString( )
methods, it
will be much easier to diagnose problems in your application. If you use
the ReflectionToStringBuilder
, you
are assured that the message printed out will be accurate; the
alternative is to have a message that may or may not be relevant—trusting developers
to keep toString( )
methods updated
manually.
This utility uses the class AccessibleObject
in the J2SE reflection
package to bypass access modifiers and access private member variables
of an object directly. If your system is running under a restrictive
SecurityManager
, you may need to
alter your configuration to allow Commons Lang to bypass these
security restrictions. Only use this reflection builder if you are
certain that your code will run in an environment without a
restrictive security policy. I use this utility in a system that runs
on a few servers in a known location, but if I were writing a reusable
library, a reflection builder would not be feasible; if someone were
to use my library in an environment with a different security policy,
calling a toString( )
may cause
problems. The relevant permission is the suppressAccessChecks
permission target of
the java.lang.reflect.ReflectPermission
class.