Осветление о obj.getClass() != getClass()
.
Это утверждение является результатом нечеткого наследования equals()
. Спецификация JLS (спецификация языка Java) указывает, что если A.equals(B) == true
, то B.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))
выдаёт true, как и должно быть.
Это выглядит очень хорошо, но посмотрите, что произойдет, если мы попытаемся использовать оба класса:
A a = new A(1);
B b = new B(1,1);
a.equals(b) == true;
b.equals(a) == false;
Очевидно, что это неправильно.
Если вы хотите обеспечить симметричное условие. a = b, если b = a и принцип подстановки Лискова 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()
тоже.