Проверяет понимание контракта equals() и правильного использования instanceof для обеспечения симметричности и транзитивности сравнения объектов.
Метод equals() в Java используется для сравнения объектов по содержимому, а не по ссылке. Его реализация должна строго следовать контракту, определённому в документации: рефлексивность, симметричность, транзивность, консистентность и сравнение с null должно возвращать false. Использование instanceof помогает соблюсти эти правила, особенно симметричность.
Оператор instanceof проверяет, является ли объект экземпляром определённого класса или его подкласса. В equals() это позволяет убедиться, что сравниваемый объект имеет совместимый тип, прежде чем приводить его к нужному классу. Это предотвращает ClassCastException и гарантирует, что сравнение происходит только между объектами, которые могут быть равны.
public class Person {
private String name;
private int age;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof Person)) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
}В этом примере instanceof проверяет, что o является Person или его подклассом. Если бы мы использовали getClass() вместо instanceof, то сравнение с подклассом всегда возвращало бы false, нарушая симметричность.
Некоторые разработчики предпочитают getClass() для строгой типизации, но это может нарушить принцип подстановки Лисков (LSP). Например, если у вас есть класс Employee extends Person, то Person.equals(Employee) может быть true, а Employee.equals(Person) — false, если в Employee используется getClass().
Используйте instanceof в equals(), когда хотите поддерживать наследование и соблюдать контракт equals(). Это особенно полезно в иерархиях классов, где подклассы могут быть равны родительским объектам. Однако если требуется строгая типизация без наследования, можно рассмотреть getClass().