There could not be any class which conform to both Same type comparison and Mixed type comparison
Same-Type Comparison
With such an implementation of equals() you can store an Employee(“Hanni Hanuta”) and a Student(“Hanni Hanuta”) into the same HashSet , but retrieval from the collection will not work as expected. You will not find any of these two contained objects when you ask the HashSet whether it contains a Person(“Hanni Hanuta”) , because all three object are unequal to each other.
Mixed-Type Comparison
In a class hierarchy, where Employee and Student are subclasses of a Person , representing roles of a person, it may make sense to compare an Employee to a Student to see whether they are the same Person . With an implementation of equals() that only allows same-type comparison an Employee and a Student would not be comparable.So mixed type comparison allows comparison between parent and child object.With this type of equals() implementation you will have problems storing an Employee(“Hanni Hanuta”) and a Student(“Hanni Hanuta”) in the same HashSet . The HashSet will reject the second add() operation, because the collection already contains an element that compares equal to the new element.
Lets see an example of Mixed-Type comparison
class BaseClass { private int field1 = 0; @Override public boolean equals(Object obj) { if (obj instanceof BaseClass) { return field1 == ((BaseClass) obj).field1; } return false; } } class BadSubClass extends BaseClass { private int field2 = 0; @Override public boolean equals(Object obj) { if (obj instanceof BadSubClass) { return super.equals(obj) && field2 == ((BadSubClass) obj).field2; } return false; } }
BaseClass baseClass = new BaseClass(); BadSubClass subClass = new BadSubClass(); System.out.println(baseClass.equals(subClass)); // prints 'true' System.out.println(subClass.equals(baseClass)); // prints 'false'
Now the above implementation does not comply to symmetric property of equals
x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
The work around for this is
class BaseClass { private int field1 = 0; @Override public boolean equals(Object obj) { if (obj != null && obj.getClass() == getClass()) { return field1 == ((BaseClass) obj).field1; } return false; } } class GoodSubClass extends BaseClass { private int field2 = 0; @Override public boolean equals(Object obj) { if (obj instanceof GoodSubClass) { return super.equals(obj) && field2 == ((GoodSubClass) obj).field2; } return false; } }