Ответ
В Java == и equals() служат для сравнения, но делают это на разных уровнях абстракции.
-
Оператор
==(оператор равенства):- Для примитивных типов (
int,char,booleanи т.д.) сравнивает значения. - Для ссылочных типов (объекты) сравнивает ссылки, т.е. проверяет, указывают ли две переменные на один и тот же объект в памяти (на один адрес).
- Для примитивных типов (
-
Метод
equals():- Определен в классе
Objectи по умолчанию также сравнивает ссылки (его реализация по умолчанию:return (this == obj);). - Его основное предназначение — быть переопределенным (overridden) в пользовательских классах для сравнения объектов по их содержимому или бизнес-логике (например, два объекта
Personравны, если у них одинаковыйid). - Многие стандартные классы (
String,Integer,LocalDate) уже имеют корректно переопределенныйequals().
- Определен в классе
Наглядный пример:
String str1 = new String("Hello");
String str2 = new String("Hello");
String str3 = str1; // str3 ссылается на тот же объект, что и str1
System.out.println("str1 == str2: " + (str1 == str2)); // false (разные объекты в памяти)
System.out.println("str1.equals(str2): " + str1.equals(str2)); // true (одинаковое содержимое)
System.out.println("str1 == str3: " + (str1 == str3)); // true (одна и та же ссылка)
// Сравнение примитивов
int a = 5;
int b = 5;
System.out.println("a == b: " + (a == b)); // true (значения равны)
Критически важные нюансы для тестирования:
- Сравнение строк: Всегда используйте
"текст".equals(переменная). Это защищает отNullPointerException, еслипеременнаяравнаnull. Обратный порядок (переменная.equals("текст")) выбросит NPE. - Сравнение с
null: Для проверки наnullвсегда используйте==или!=. Выражениеobj.equals(null)либо вернетfalse(еслиequalsкорректно реализован), либо выбросит NPE. - Контракт
equals()иhashCode(): Если вы переопределяетеequals()в своем классе (например, в классе-модели для тестовых данных), вы обязаны переопределить иhashCode(), чтобы объекты, которые равны поequals(), имели одинаковый хэш-код. Нарушение этого контракта приведет к некорректной работе сHashSet,HashMapи другими коллекциями, основанными на хэше.
Ответ 18+ 🔞
А, ну это классика, ёпта! Сейчас объясню, как не наступить на эти грабли, а то потом будешь головой об стенку биться, когда тесты начнут гореть из-за какой-то хуйни.
Смотри, в Java есть две штуки для сравнения: == и equals(). И они, блядь, делают разное, хоть и выглядят похоже. Это как сравнивать двух близнецов: с виду одно и то же, а по факту — два разных человека.
== (оператор равенства)
- Для примитивов (
int,char,boolean) — сравнивает значения. Всё просто: пять — это пять. - Для объектов — сравнивает ссылки в памяти. То есть он проверяет, не одна ли это и та же квартира, а не то, что в обеих живут Ивановы с двумя детьми. Даже если в обеих трёшках живут одинаковые семьи, но это разные квартиры в разных домах —
==скажет «нет, нихуя не одно и то же».
equals() (метод)
- По умолчанию, из коробки, он делает ровно то же самое, что и
==— тыкает пальцем в адреса памяти. Его реализация в классеObject— это простоreturn (this == obj);. Честно, да? - Но вся его сила в том, что его можно переопределить. Это как взять стандартный кухонный нож и заточить его под свою, ебать, специфическую задачу — например, чистить рыбу. Многие умные дядьки из Java уже так и сделали для популярных классов вроде
StringилиInteger. В нихequals()сравнивает уже не адреса, а содержимое объектов. Две строки"Hello"— равны, даже если они висят в разных углах памяти.
Пример, чтобы вообще всё стало ясно:
String str1 = new String("Hello");
String str2 = new String("Hello");
String str3 = str1; // str3 — это просто второй ключ от той же самой квартиры, что и у str1
System.out.println("str1 == str2: " + (str1 == str2)); // false (ёпта, разные объекты!)
System.out.println("str1.equals(str2): " + str1.equals(str2)); // true (а содержимое-то одинаковое!)
System.out.println("str1 == str3: " + (str1 == str3)); // true (ну это одна и та же ссылка, тут и ежу понятно)
// С примитивами проще
int a = 5;
int b = 5;
System.out.println("a == b: " + (a == b)); // true (пять — оно и в Африке пять)
А теперь, чувак, самое важное, что тебя на собесе или в тестах подловит, если не знаешь:
-
Сравнивая строки, всегда делай так:
"ожидаемоеЗначение".equals(переменнаяИзТеста). Почему? Да потому что еслипеременнаяИзТеставнезапноnull, то этот вызов просто вернётfalse. А если сделать наоборот,переменнаяИзТеста.equals("ожидаемоеЗначение"), то тебе в лоб прилетитNullPointerException, и тест накроется медным тазом. Запомни этот финт ушами. -
Проверка на
null— только через==или!=. Никогда не пишиobj.equals(null). Это либо бессмысленно (вернётfalse), либо, если реализацияequals()кривая, опять же приведёт к пиздецу. Дляnullесть свой, отдельный оператор. -
Священный контракт
equals()иhashCode(). Вот это, блядь, важно. Если ты в своём классе (например, в классе-модельке для тестовых данных) переопределилequals(), чтобы сравнивать объекты по какому-то полюid, то ты ОБЯЗАН переопределить иhashCode()так, чтобы у равных поequals()объектов хэш-коды тоже были одинаковые. Если этого не сделать, то твои объекты начнут вести себя вHashSetилиHashMapкак последние распиздяи — ты их положишь в коллекцию, а потом не найдешь, потому что они будут сидеть не в той корзине. Доверия к такому коду — ноль ебать.