Переопределенный метод стринг работает только если вызываю его явно

Изначальный код выглядел так:

enter image description here

Списки выглядят так:

enter image description here

А сообщение было такое:

enter image description here

Затем при поэлементной проверке оказалось, что если не вызывать метод toString явно, то сравнение возвращает false, а если вызывать явно, то true

Переопределенный метод toString:

enter image description here

В итоге код, который заработал:

enter image description here

В чем была проблема?


Ответы (1 шт):

Автор решения: AndrewThomas

При сравнении одного объекта класса Student из списка students1 с другим объектом класса Student из списка students2 у одного из них вызывается метод equals(Object other). Это метод класса Object, и по умолчанию он сравнивает, указывают ли ссылки на один и тот же объект в памяти, если нет - возвращает false. Т.е. он не сравнивает результат вызова метода toString().

Хотя в сравниваемых объектах класса Student все поля идентичны, без переопределения метода equals() программа не знает, как конкретно их сравнивать, поэтому сравнивает ссылки.
Предположу, что в списки students1 и students2 были помещены не одни и те же объекты, а разные объекты, созданные через вызов оператора new и помещение в конструкторы идентичных данных, и хотя строчное представление объектов идентично, сами объекты в памяти - разные.

Поэтому в классе Student необходимо переопределить метод equals, например вот так:

@Override
public boolean equals(Object other) {
    if (this == other) return true;
    if (other == null || getClass() != other.getClass()) return false;
    Student student = (Student) other;
    return Objects.equals(id, student.id) && Objects.equals(name, student.name);;
}

Также в большинстве случаев рекомендовано вместе с методом equals() переопределять метод hashCode(). Об этом довольно много написано, также информацию об этом можно найти в исходном коде на сайте Oracle.

→ Ссылка