Ответ
В Java строки могут быть разными объектами даже с одинаковым содержимым из-за того, как работает String Pool.
Если строка создана через new String(), она всегда будет новым объектом в куче, даже если такое же значение есть в пуле. При сравнении через == проверяется ссылка, а не содержимое.
String a = "hello"; // попадает в String Pool
String b = new String("hello"); // новый объект в куче
System.out.println(a == b); // false - разные объекты
System.out.println(a.equals(b)); // true - одинаковое содержимое
Для сравнения содержимого всегда используйте equals(). Для интернирования строк можно использовать intern().
Ответ 18+ 🔞
А, ну это классика, блядь! Тут каждый второй новичок на этом подгорает, ебать мои старые костыли. Смотри, в Java со строками такая хитрая жопа устроена, называется String Pool.
Представь себе: есть такой общий склад, куда складывают все одинаковые строковые таблички. Ты пишешь String a = "hello" — и Java такая: «Так, стопэ. У нас уже есть табличка "hello" на складе? Есть? Отлично, вот тебе ссылка на неё, не будем новую городить». Это и есть пул.
А теперь приходит распиздяй и пишет new String("hello"). И тут Java уже не хитрит, она тупо создаёт новый, отдельный объект в куче, как с любым другим классом. И получается, что по смыслу строки одинаковые — «hello», а в памяти это два разных объекта, две разные коробки с одинаковой надписью.
Вот поэтому, когда ты их сравниваешь через ==, он смотрит: «А это одна и та же коробка? Нет? Ну значит false». А equals() заглядывает внутрь коробки и проверяет, одинаковая ли там надписуля. И говорит: «Да, true, оба "hello"».
String a = "hello"; // Лезет в общий склад (String Pool), берёт оттуда
String b = new String("hello"); // Хуяк — и новая коробка в куче, хоть и с тем же текстом
System.out.println(a == b); // false — потому что это РАЗНЫЕ КОРОБКИ, Карл!
System.out.println(a.equals(b)); // true — потому что внутри обе коробки кричат "hello"
Так что запомни, чувак: для сравнения того, что внутри, всегда юзай equals(). А если ты создал строку через new и хочешь затолкать её в общий склад, чтобы оптимизировать память, есть метод intern(). Он твою новую коробку проверит, и если такая надпись в пуле уже есть — вернёт ссылку на старую из пула. Но это уже тонкости, на первых порах главное — не путать == и equals(), а то будет вам хиросима и нигерсраки в отладке.