Ответ
Метод equals() нужно переопределять, когда логика сравнения объектов вашего класса должна основываться на равенстве их внутреннего состояния (полей), а не на равенстве ссылок в памяти (что делает реализация по умолчанию от Object).
Ключевые ситуации для переопределения equals():
- Использование объектов в коллекциях, основанных на хэше (
HashMap,HashSet,Hashtable). Для корректной работы этих коллекцийequals()должен согласовываться сhashCode(). - Семантическое сравнение. Например, два объекта
Personс одинаковымidилиemailдолжны считаться одним и тем же человеком, даже если это разные экземпляры в памяти. - Тестирование. Для удобного сравнения ожидаемого и фактического объекта в unit-тестах (хотя часто для этого используют библиотеки вроде AssertJ).
Контракт метода equals() (обязательные правила):
- Рефлексивность:
x.equals(x)всегдаtrue. - Симметричность: Если
x.equals(y)вернетtrue, то иy.equals(x)должно вернутьtrue. - Транзитивность: Если
x.equals(y)иy.equals(z)вернутtrue, то иx.equals(z)должно вернутьtrue. - Консистентность: Многократные вызовы
x.equals(y)должны consistently возвращать одно и то же значение, если поля, участвующие в сравнении, не менялись. - Сравнение с null:
x.equals(null)всегда должно возвращатьfalse.
Пример переопределения с использованием Objects.equals():
public class Person {
private final Long id;
private final String name;
private final String email;
@Override
public boolean equals(Object o) {
// 1. Проверка на ссылочное равенство
if (this == o) return true;
// 2. Проверка на null и совпадение класса
if (o == null || getClass() != o.getClass()) return false;
// 3. Приведение типа и сравнение значимых полей
Person person = (Person) o;
return Objects.equals(id, person.id) &&
Objects.equals(email, person.email); // email как уникальный идентификатор
// Имя (name) может не участвовать в сравнении, если оно не определяет уникальность
}
@Override
public int hashCode() {
// hashCode должен строиться по тем же полям, что и equals
return Objects.hash(id, email);
}
}
Важное правило: Если вы переопределяете equals(), вы обязаны переопределить hashCode(), чтобы выполнялось условие: если два объекта равны по equals(), то их хэш-коды должны быть одинаковыми.