Рассмотрим следующие классы:
public class Base {
protected int i = 0;
public Base(int i) {
this.i = i;
}
public Base(Base b) {
this(b.i);
}
public Base foo() {
return new Base(this);
}
}
public class Sub extends Base {
public Sub(int i) {
super(i);
}
public Sub(Sub s) {
super(s.i * 2);
}
public Base foo() {
return this;
}
@Override
public boolean equals(Object o) {
return ((Sub) o).i == this.i;
}
public static void main(String[] args) {
Base b1 = new Base(1);
Base b2 = b1;
Base b3 = b2.foo();
Base b4 = new Sub(1);
Base b5 = b4.foo();
System.out.println(b1.equals(b3));
}
}
Печатный результат не соответствует false
. Я заметил, что переопределенный метод equals(Object o)
никогда не попадается, и я подозреваю, конечно, что это проблема (в противном случае он напечатал бы true
).
Почему это?
Вы вызываете b1.equals(b3)
- b1
- это экземпляр Base
, а не Sub
, так что вы не можете вызвать ваш метод переопределения.
Heck, даже b3.equals(b1)
ничего не назовет на Sub
, так как b3
ссылается на экземпляр Base
.
Только b4
и b5
относятся к экземплярам Sub
, поэтому только b4.equals(...)
или b5.equals(...)
вызовут ваш переопределенный метод. Кроме того, поскольку вы безоговорочно применяете метод equals
, b4.equals(b1)
(например) генерирует исключение, а не возвращает false
.
Посмотрите, как работает ваш код (в основном методе)
Base b1 = new Base(1);
: - Создает новую базу (1) Объект и ссылка - b1
. Позволяет называть этот объект первым объектом.
Base b2 = b1;
: - создает ссылочную переменную типа Base и присваивает значение переменной b1
, поэтому оба b1 и b2 ссылаются на один и тот же объект (первый объект)
Base b3 = b2.foo();
: - Создает опорную переменную типа Base b3.
foo()
в первом базовом объекте вызывается и возвращает новый базовый объект (второй объект), где он атрибут value = первый объект я значение атрибута
Base b4 = new Sub(1);
: - Создает новый объект Sub (1), а ссылка - b4
. Позволяет называть этот объект третьим объектом.
Base b5 = b4.foo();
: - создает опорную переменную типа Base b5.
foo()
в третьем объекте (Sub), и он возвращает свою собственную ссылку в качестве базового типа. Sub может вернуть свою собственную ссылку в качестве базы, потому что Base - это Super Class.
b1.equals(b3)
: - теперь вы вызывали метод equals объекта, который ссылается на b1
. b1
относится к объекту Base
типа (первый объект). равен методу базового объекта. Он имеет метод равных по умолчанию. (переопределенный метод находится в Sub-объекте, и это не Sub-объект.) Метод equals по умолчанию проверяет, являются ли их хэш-коды одинаковыми. b1 - первый объект, b3 - третий объект. поэтому b1 и b3 не равны.
Таким образом, вывод должен быть false
.
Здесь нет никакого превалирующего действия.
Если вы изменили код следующим образом, вы можете получить переопределенный вывод
Base b1 = new Sub(1);
Base b3 = b1.foo();
Base b4 = new Sub(1);
Base b5 = b4.foo();
System.out.println(b4.equals(b3));