注:本文转自《白煮蛋的博客》
关于obj.getClass() != getClass()
.
该语句是equals()
继承不友好的结果。JLS(Java 语言规范)指定 if A.equals(B) == true
thenB.equals(A)
还必须返回true
. 如果您省略该语句,继承覆盖equals()
(并更改其行为)的类将破坏此规范。
考虑以下示例,说明省略语句时会发生什么:
class A {
int field1;
A(int field1) {
this.field1 = field1;
}
public boolean equals(Object other) {
return (other != null && other instanceof A && ((A) other).field1 == field1);
}
}
class B extends A {
int field2;
B(int field1, int field2) {
super(field1);
this.field2 = field2;
}
public boolean equals(Object other) {
return (other != null && other instanceof B && ((B)other).field2 == field2 && super.equals(other));
}
}
另外new A(1).equals(new A(1))
,new B(1,1).equals(new B(1,1))
结果应该是真实的。
这看起来都很好,但是看看如果我们尝试使用这两个类会发生什么:
A a = new A(1);
B b = new B(1,1);
a.equals(b) == true;
b.equals(a) == false;
显然,这是错误的。
如果要确保对称条件。a=b if b=a 和 Liskov 替换原则super.equals(other)
不仅在实例的情况下调用B
,而且在实例之后检查A
:
if (other instanceof B )
return (other != null && ((B)other).field2 == field2 && super.equals(other));
if (other instanceof A) return super.equals(other);
else return false;
这将输出:
a.equals(b) == true;
b.equals(a) == true;
如果a
不是 的引用B
,那么它可能是类的引用A
(因为您扩展了它),在这种情况下您也super.equals()
调用.