Wednesday, August 24, 2016

The Easy Way to Write toString(), equals() and hashCode() Methods

Once you’ve written a toString() method, it starts to get boring to write more especially if you want to include a lot of instance variables. Luckily, there is an open source library that takes care of it for you. Apache Commons Lang provides some methods that you might wish were in core Java.
This is all you have to write to have Apache Commons return all of the instance variables in a String:

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

You might be wondering what this reflection thing is that is mentioned in the method name. Reflection is a technique used in Java to look at information about the class at runtime. This lets the ToString Builder class determine what are all of the instance variables and to construct a String with each.
When testing your code, there is a benefit to not having information in toString() that isn’t useful to your caller. Apache Commons accounts for this as well.
You could write

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

There are a few other styles that support letting you choose to omit the class names or the instance variable names.


Like toString(), you could use Apache Commons Lang to do a lot of the work for you. If you want all of the instance variables to be checked, your equals() method could be one line:

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

This is nice. However, for equals(), it is common to look at just one or two instance variables rather than all of them.

@Override
public boolean equals(Object obj) {
if (!(obj instanceof LionEqualsBuilder))
return false;
Lion other = (Lion) obj;
return new EqualsBuilder().appendSuper(super.equals(obj)).append(idNumber, other.idNumber)
.append(name, other.name).isEquals();
}

Not quite as elegant, right? You have to remember to handle the null and instanceof guard conditions first. It is still better than having to code the whole thing by hand, though. Comparing the idNumber is easy because you could call ==. Comparing the name means checking that either both names are null or the names are the same. If either name is null, you need to return false. This logic is a bit messy if you write it out by hand.


You probably thought that this was going to be about the Apache Commons Lang class for hash code. There is one, but it isn’t the easiest way to write hash code.
It is easier to code your own. Just pick the key fields that identify your object (and don’t change during the program) and combine them:

@Override
public int hashCode() {
return keyField + 7 * otherKeyField.hashCode();
}

It is common to multiply by a prime number when combining multiple fields in the hash code. This makes the hash code more unique, which helps when distributing objects into buckets.

No comments:

Post a Comment