I have an address object that I want to create an equals method for. I could have made this quite simple by doing something like the following (shortened a bit):
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Address other = (Address) obj;
return this.getStreet().equals(other.getStreet())
&& this.getStreetNumber().equals(other.getStreetNumber())
&& this.getStreetLetter().equals(other.getStreetLetter())
&& this.getTown().equals(other.getTown());
}
Problem is, some of these might be null. I will in other words get a NullPointerException
if there is no street letter in this address.
How can I write this in a clean way while taking null values into account?
You can use a helper method like
public static boolean isEqual(Object o1, Object o2) {
return o1 == o2 || (o1 != null && o1.equals(o2));
}
Google Guava provides Objects.equal(Object, Object) which checks for equality while taking into consideration that either of the parameters might be null:
...
return Objects.equal(this.getStreet(), other.getStreet())
&& Objects.equal(this.getStreetNumber(), other.getStreetNumber())
&& Objects.equal(this.getStreetLetter(), other.getStreetLetter())
&& Objects.equal(this.getTown(), other.getTown());
It's also worth pointing out that Objects has other helper methods for implementing hashCode() and toString().
You could do the following:
public boolean equals(Object obj)
{
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Address other = (Address) obj;
return equals(this.getStreet(),other.getStreet())
&& equals(this.getStreetNumber(), other.getStreetNumber())
&& equals(this.getStreetLetter(), other.getStreetLetter())
&& equals(this.getTown(), other.getTown());
}
private boolean equals(Object control, Object test) {
if(null == control) {
return null == test;
}
return control.equals(test);
}
Java 7 introduced built-in support for this use case with the java.util.Objects class see:
I have a helper class Checker w/ a static method:
public static boolean isEquals(final Object o1, final Object o2) {
return o1 == null ? o2 == null : o1.equals(o2);
}
so, in the equals method,
return Checker.isEquals(this.getStreet(), other.getStreet())
&& Checker.isEquals(this.getStreetNumber(), other.getStreetNumber())
&& Checker.isEquals(this.getStreetLetter(), other.getStreetLetter())
&& Checker.isEquals(this.getTown(), other.getTown());
There is no really clean way to do that; the best option is probably to have your IDE generate the code for you. Eclipse can do it via the Source -> Generate hashCode() and equals() context menu.
You can use Objects.equal from Googles guava or the EqualsBuilder from apache commons
I'd consider defining some of the equals methods as static class methods, like say for the Street objects. This way you don't ever attempt to call the .equals() method on a null.
A sample function might look like:
public static boolean equals(Object one, Object two)
Also, it's good practice to put checks like
if (obj == null)
return false;
at the very beginning of a function.
Apache Commons Lang provides the EqualsBuilder helper class for equality comparissons. There is also one for hash codes.
return new EqualsBuilder()
.append(this.getStreet(), other.getStreet())
.append(this.getStreetNumber(), other.getStreetNumber()
.append(this.getStreetLetter(), other.getStreetLetter())
.append(this.getTown(), other.getTown())).isEquals();
来源:https://stackoverflow.com/questions/5661936/java-clean-way-of-avoiding-nullpointerexception-in-equals-checks