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.

Advertisements

Using CompareToBuilder to implement Comparable interface

Many a times, we need to implement the java.lang.Comparable interface. This interface has a single method int compareTo(Object o). Apache’s Commons Lang library provides a utility class – CompareToBuilder which makes it easy to write the compareTo() method. The method is consistent with with equals() and hashCode() methods built using EqualsBuilder and HashCodeBuilder (provided the same fields are used in all of them). A typical use of the class is as follows:

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

  public int compareTo(Account account) {
    return new CompareToBuilder()
        .append(this.id, account.id)
        .append(this.firstName, account.firstName)
        .append(this.lastName, account.lastName)
        .append(this.emailAddress, account.emailAddress)
        .append(this.creationDate, account.creationDate)
        .toComparison();
  }
}

We first create an instance of the CompareToBuilder. The append method takes two arguments – the two fields we want to compare. It returns an instance of CompareToBuilder so multiple calls to the append method can be chained (as in the above example). Finally we call the toComparison() method which returns the appropriate value to the caller.