Implementing equals(), hashCode(), toString() & compareTo() using reflection

In my previous posts, I wrote about the various utility classes provided by Apache’s commons lang library for implementing commonly used methods (equals(), hashCode() etc.). All of these classes also provide the option of implementing these methods using reflection. That reduces your code for implementing any of these methods to just writing one line! For example, to implement toString() method using reflection, use the reflectionToString() static method of the ToStringBuilder class. Here’s the implementation of all the above methods using reflection in a sample class:

public class Account implements Comparable {
  private long id;
  private String firstName;
  private String lastName;
  private String emailAddress;
  private Date creationDate;

  public boolean equals(Object obj) {
    return EqualsBuilder.reflectionEquals(this, obj);
  }

  public int hashCode() {
    return HashCodeBuilder.reflectionHashCode(this);
  }

  public int compareTo(Account account) {
    return CompareToBuilder.reflectionCompare(this, account);
  }

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

However, these methods use AccessibleObject.setAccessible() method to change the visibility of class fields (since generally these fields are private). This will not work under a security manager, unless appropriate permissions are set up correctly. Also, these methods are slower than testing explicitly.

Using ToStringBuilder to easily write toString() method

Another useful class in Apache’s Commons Lang library is the ToStringBuilder class. I’ve already covered the HashCodeBuilder and the EqualsBuilder classes in previous posts. The ToStringBuilder class provides you methods to easily write the toString() method in your class. The program below explains how to use it:

public class Account implements Comparable {
  private long id;
  private String firstName;
  private String lastName;
  private String emailAddress;
  private Date creationDate;

  public String toString() {
    return new ToStringBuilder(this)
        .append("id", this.id)
        .append("firstName", this.firstName)
        .append("lastName", this.lastName)
        .append("emailAddress", this.emailAddress)
        .append("creationDate", this.creationDate)
        .toString();
  }
}

The output is of the form Account@43d1[id=1, firstName=Parambir, lastName=Singh, emailAddress=test@parambir.com, creationDate=Mon Feb 22 10:54:29 IST 2010].

First we create an object of the ToStringBuilder class (and pass the ‘this’ reference to the constructor). Then we use the append method to add each field that we want to print in the toString() method. Append method takes two arguments: fieldName and fieldValue. e.g. builder.append("name", this.name). If the value of the field “name” was “Param”, it will be printed as “name=Param”. The append method returns an instance of the ToStringBuilder, so the calls to multiple append methods can be chained (as in the example above).

Some other useful methods of the class are:

  • append(value) – No field name is printed in this case, only the value is printed.
  • append(name, value) – The field will be printed in the form “name=value”.
  • appendSuper(String s) – Appends the toString from the super class.

The class also takes care of printing arrays properly!