Take a look at "Implementing equals() To Allow Mixed-Type Comparison" from Angelika Langer .
Here is a brief explanation of some problems and a possible solution:
The equals contract says (amongst others):
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
That means you might get problems if your sub class is introducing new fields and you're comparing an object of the base class (or another sub class that doesn't override equals) to an object of this sub class.
Do NOT do the following:
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;
}
}
because you get
BaseClass baseClass = new BaseClass();
BadSubClass subClass = new BadSubClass();
System.out.println(baseClass.equals(subClass)); // prints 'true'
System.out.println(subClass.equals(baseClass)); // prints 'false'
A possible solution:
Replace the instanceof
-check with a class comparison:
obj != null && obj.getClass() == getClass()
With this solution an object of BaseClass
will never be equal to an object of any subclass.
If you create another SubClass
without an @Override
of the equals
method, two SubClass
-objects can be equal to each other (if the BaseClass.equals
check decides so) out of the box, but a SubClass
-object will never be equal to a BaseClass
-object.
A good implementation could be as follows:
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;
}
}
Please refer to the article mentioned above for more advanced problems and their solutions.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…