We’ve earlier written a post about Recipe for a high-quality “equals” method. This is harder to get right in the case of inheritance.
As it says here the contract of the equals method in Object specifies that equals must implement an equivalence relation on non-null objects:
Consider two classes: A and B that extends class A.
public class A { } public class B extends A { }
Now, if we have two objects of type B with different values from class A, then these two objects can not be equal. That means that we cannot not to take into consideration equals method from class A when writing an equals method for class B:
public class A { private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } @Override public int hashCode() { return Objects.hash(id); } @Override public boolean equals(Object obj) { if(obj == null) { return false; } if(!(obj instanceof A)) { return false; } A other = (A)obj; return Objects.equals(this.id, other.id); } } public class B extends A { private String id; public String getId() { return id; } public void setId(String id) { this.id = id; } @Override public int hashCode() { return Objects.hash(super.hashCode(), id); } @Override public boolean equals(Object obj) { if(obj == null) { return false; } if(!(obj instanceof B)) { return false; } B other = (B)obj; return super.equals(obj) && Objects.equals(this.id, other.id); } }
We added super.hashCode() in hashCode method and super.equals(obj) in equals in order to implement the right equality check.
A good thing in this design will be to make class A abstract then there won’t be logic problems when comparing A and B like this:
A.equals(B)
B.equals(A)
Senior Software Engineer developing all kinds of stuff.