Ответ
При реализации equals() необходимо соблюдать его контракт:
- Рефлексивность:
x.equals(x)→true. - Симметричность:
x.equals(y)→trueтогда и только тогда, когдаy.equals(x)→true. - Транзитивность: Если
x.equals(y)иy.equals(z), тоx.equals(z). - Согласованность: Многократные вызовы возвращают одинаковый результат, если объекты не изменялись.
- Сравнение с 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).