Ответ
Метод equals() используется для сравнения объектов на содержательное равенство, а не просто ссылочное (как ==). По умолчанию он сравнивает ссылки, но его можно переопределить для логики сравнения полей.
Пример переопределения:
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return age == person.age && Objects.equals(name, person.name);
}
Важно:
- Всегда переопределять
hashCode()вместе сequals()(иначе нарушится контракт для коллекций). - Проверять тип (
instanceofилиgetClass()). - Учитывать
nullи рефлексивность/симметричность/транзитивность.
Ответ 18+ 🔞
Э, слушай, вот тебе история про этот ваш equals(). Ну, то есть, не моя история, а вообще, как оно работает. Представь, что ты в баре, и тебе показывают две одинаковые бутылки пива. По этикетке — одно и то же, но одна в твоей руке, а другая у соседа на столе. Оператор == — это как посмотреть на руку: «Это моя бутылка? Нет, это его бутылка. Значит, не одно и то же». А equals() — это как попробовать: «О, оба — «Балтика №9»! По содержанию — одинаковое говно! Значит, равны».
По умолчанию equals() ведёт себя как тупой ==, то есть сравнивает ссылки — чья рука держит. Но это, блядь, не всегда то, что надо. Поэтому его надо переопределять, чтобы он смотрел не на руку, а на то, что внутри объекта.
Вот смотри, как это выглядит в коде, если бы мы сравнивали людей:
@Override
public boolean equals(Object obj) {
// Если это один и тот же объект в памяти — сразу true, нехуй думать
if (this == obj) return true;
// Если нам подсунули null или объект вообще другого класса — false, ядрёна вошь!
if (obj == null || getClass() != obj.getClass()) return false;
// Приводим тип. Кастим, блядь.
Person person = (Person) obj;
// И вот теперь сравниваем ПОЛЯ: возраст и имя.
return age == person.age && Objects.equals(name, person.name);
}
Вот и вся магия. Но есть, сука, важные нюансы, про которые все постоянно забывают, а потом у них всё ебётся.
Главные правила, которые надо выжечь себе на подкорке:
-
hashCode()— твой близнец-брат. Если переопределилequals(), обязательно переопредели иhashCode(). Иначе коллекции вродеHashMapилиHashSetпросто сойдут с ума и будут терять твои объекты, как носки в стиральной машине. Это, ёпта, железное правило. Нарушишь — получишь неработающую хеш-таблицу, и будешь потом неделю искать, куда делся твой элемент. Доверия к такому коду — ноль ебать. -
Тип проверяй. Обязательно убедись, что тебе скормили объект того же класса.
instanceofилиgetClass()— выбирай по ситуации, но не пропускай этот шаг. А то какой-нибудьпидарас шерстянойв виде объектаCarпролезет в сравнение сPerson, и всё упадёт сClassCastException. -
Не забудь про
null. Сравнивать сnullвсегда должно возвращатьfalse. Это как спросить у пустого стула: «Ты Вася?». Нет, стул — не Вася. -
Свойства контракта. Рефлексивность (
x.equals(x)— всегдаtrue), симметричность (еслиx.equals(y), то иy.equals(x)) и транзитивность. Звучит занудно, но если на этом сэкономить, получится такая пиздопроебибна в логике, что объекты будут равны сами себе только по вторникам.
Короче, суть в чём: equals() — это твой инструмент, чтобы сказать системе: «Слушай, вот эти два разных объекта в памяти я считаю одинаковыми, потому что у них совпадают вот эти поля». А == — это просто проверка, не одно ли это и то же место в памяти. Всё, вопрос закрыт.