Ответ
Метод equals() в Java сравнивает объекты по их содержимому, а не по ссылке (в отличие от ==). По умолчанию (в классе Object) он ведёт себя как ==, но его можно переопределить для логического сравнения полей.
Пример переопределения:
@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);
}
Важные правила:
- Рефлексивность:
x.equals(x)→true - Симметричность:
x.equals(y)==y.equals(x) - Транзитивность: если
x.equals(y)иy.equals(z), тоx.equals(z) - Консистентность: повторные вызовы дают одинаковый результат
x.equals(null)→false
Ответ 18+ 🔞
А, ну это же классика, ёпта! Сейчас объясню на пальцах, чтобы даже мартышлюшка поняла.
Вот смотри, в Java есть две штуки для сравнения: оператор == и метод equals(). Так вот, == — это как будто ты смотришь на два одинаковых чёрных мерседеса и говоришь: «Это одна и та же тачка?». Он проверяет, ссылаются ли обе переменные на один и тот же объект в памяти. А equals() — это уже вопрос: «А эти две тачки одинаковые по характеристикам? Одинаковый двигатель, цвет и хрень на лобовом?». Он должен сравнивать по смыслу, по содержимому.
По умолчанию, если ты не паришься, equals() в классе Object ведёт себя ровно так же, как ==. То есть, доверия к нему — ебать ноль. Он просто сравнивает ссылки. Поэтому его надо переопределять, если тебе нужна нормальная, человеческая логика сравнения.
Вот смотри, как это обычно выглядит в коде. Представь, у нас класс Person (Человек, не полупидор какой-нибудь).
@Override
public boolean equals(Object obj) {
// 1. Если это один и тот же объект — сразу true, нехуй мозги парить
if (this == obj) return true;
// 2. Если нам подсунули null или объект вообще другого класса — false, ясень пень
if (obj == null || getClass() != obj.getClass()) return false;
// 3. Приводим тип. Теперь мы знаем, что это Person.
Person person = (Person) obj;
// 4. Сравниваем ВСЕ значимые поля. Имя и возраст в нашем случае.
return age == person.age && Objects.equals(name, person.name);
}
Видишь? Всё логично. Сначала отсекаем очевидную хуйню, потом кастуем и сравниваем каждое поле. Objects.equals() — это такая удобная штука, которая не сломается, если name будет null.
А теперь, чувак, самое важное — правила, которые нельзя нарушать, иначе весь твой код превратится в пиздопроебибну, которую невозможно отладить. Их как заповеди помни:
- Рефлексивность:
x.equals(x)всегда должен возвращатьtrue. Объект должен быть равен самому себе, это же ебать очевидно! Если нет — ты конченый. - Симметричность: Если
x.equals(y)вернулtrue, то иy.equals(x)обязан вернутьtrue. Не может быть так, что Вася равен Пете, а Петя Васе — нет. Это уже какая-то хитрая жопа получается. - Транзитивность: Если
xравенy, аyравенz, тоxобязан быть равенz. Логика, блядь, а нехуй с горы. - Консистентность: Сколько раз ни вызывай
equals()на неизменённых объектах — результат должен быть одинаковый. Не может он сегодня сказатьtrue, а завтра —false. Иначе это волнение ебать на ровном месте. - Сравнение с null:
x.equals(null)всегда должен бытьfalse. НикакихNullPointerException! Простоfalseи точка.
Вот если эти правила соблюдаешь — ты молодец, код будет работать предсказуемо. А если начнёшь выёбываться и нарушать — готовься к тому, что коллекции (HashSet, HashMap) начнут глючить так, что сам от себя охуеешь. Они же внутри на equals() и hashCode() завязаны.
Короче, переопределяй equals() с умом, и будет тебе счастье. А не переопределишь или сделаешь криво — сам потом будешь ебать копать, ища баг.