Archive

Posts Tagged ‘toString’

Easy Java toString() methods using Apache commons-lang ToStringBuilder

May 21, 2010 2 comments

One of the disciplines I try to have while developing Java code is always overriding the default toString, equals, and hashCode methods. I have found that most of the modern IDE’s have a way to generate these methods. My IDE of choice, IntelliJ IDEA, does have this functionality but I find it’s implementations to be sub par. Here is an example of an IntelliJ generated toString method for a class…

@Override
public String toString() {
    return "Person{" +
        "name=" + name +
        ", age=" + age +
        '}';
}

My biggest problems with this implementation are:

  1. Hard-coded, static strings for class and field names makes the amazing refactoring features of IntelliJ less reliable.
  2. Not using StringBuilder makes this code harder to read and slightly more resource intensive.
  3. Only fields of this class can be used; all inherited fields, even protected ones, are not included.

This was just not good enough. I started to investigate if anyone had written some kind of library which could reflectively look at an Object and produce a complete (private and inherited fields included) and consistent toString representation. Sure enough, I discovered that one of the Apache Commons libraries provided exactly this functionality. The commons-lang project has a class called ToStringBuilder which has a static method on it that uses reflection to generate a string which contains a all of a classes fields. The string’s format is consistent and can be controlled by the ToStringStyle class which has several useful formats built-in and also lets to implement your own. You can now write any object’s toString method as follows:

@Override
public String toString() {
    return ToStringBuilder.reflectionToString(this);
}

If you are using maven as your project management tool, you can add the following dependency into your pom.xml file in order to be able to use the commons-lang library in your project.

<dependency>
  <groupId>commons-lang</groupId>
  <artifactId>commons-lang</artifactId>
  <version>2.5</version>
</dependency>

Normally I would try to avoid reflection in production code when possible due to it’s reported slower performance, however I find the only time I am actually using toString methods is usually in debugging or testing where speed is not my number one concern. If you don’t feel reflection is a good solution for you, the ToStringBuilder class does have several instance methods which follow the traditional ‘builder’ pattern which allows you to manually choose the fields which will be included in the string representation of your object. Here is example of that usage pattern:

public String toString() {
    return new ToStringBuilder(this).
        append("name", name).
        append("age", age).
        append("smoker", smoker).
        toString();
}

This usage does have some of the same problems as the original implementation like it requires the field identifiers to be static strings. This does however allow you to ensure a consistent format of the resulting string and it also has the ability to include the any super classes’ toString result using the appendSuper() method.

If you are using Eclipse or NetBeans, I understand there are very good plugins which can build very good toString representations but this functionality is unfortunately not enough for me to give up the refactoring support IntelliJ provides. The above solution would also help though if you have some developers on a team using different IDE; using a library to toString representations is better than IDE dependent tools since it maintains consistency between environments.

The ToStringBuilder class is just one of many useful utility classes provided by the commons-lang library and the commons-lang library is just one of the useful libraries provided by the Apache Commons project. Make sure to check it out anytime you find yourself writing some code and asking yourself “Hasn’t someone done this already?”

Follow

Get every new post delivered to your Inbox.