Как правильно реализовать метод equals() в Java?

«Как правильно реализовать метод equals() в Java?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

При реализации equals() необходимо соблюдать его контракт:

  1. Рефлексивность: x.equals(x)true.
  2. Симметричность: x.equals(y)true тогда и только тогда, когда y.equals(x)true.
  3. Транзитивность: Если x.equals(y) и y.equals(z), то x.equals(z).
  4. Согласованность: Многократные вызовы возвращают одинаковый результат, если объекты не изменялись.
  5. Сравнение с null: x.equals(null)false.

Обязательно переопределяйте hashCode(), чтобы объекты, признанные равными по equals(), имели одинаковый хеш-код. Это критично для корректной работы HashMap, HashSet.

Шаблон реализации с использованием java.util.Objects:

@Override
public boolean equals(Object o) {
    // 1. Проверка ссылки
    if (this == o) return true;
    // 2. Проверка типа и null
    if (o == null || getClass() != o.getClass()) return false;
    // 3. Приведение типа и сравнение полей
    MyClass other = (MyClass) o;
    return Objects.equals(this.field1, other.field1) &&
           Objects.equals(this.field2, other.field2) &&
           this.field3 == other.field3; // для примитивов
}

@Override
public int hashCode() {
    // Генерация хеш-кода на основе тех же полей, что и в equals()
    return Objects.hash(field1, field2, field3);
}

Важные моменты:

  • Используйте Objects.equals() для безопасного сравнения ссылок (включая null).
  • Для примитивных типов используйте ==.
  • Сначала сравнивайте наиболее «дешевые» или чаще различающиеся поля.
  • Рассмотрите возможность использования автоматической генерации через IDE или Lombok (@EqualsAndHashCode).