Метод equals в Java

Часто при программировании нам приходиться проверять равенство объектов. Но как же работает сравнение объектов в языке Java? Расскажем вам в этой статье.

Метод equals в Java

Статья ориентирована на читателей среднего уровня подготовки Java.

Сравнение с помощью == и equals в Java

Приведем пример программного кода:

Но, в чем же разница между этими двумя записями? Какое отличие между оператором сравнения == и методом equals?

Все очень просто. Метод equals в Java при сравнении проверяет и сопоставляет само содержимое объектов (их значения) и на основе этого делает заключение равны они (true) или нет (false).

Оператор == (в случае с примитивными типами данных) сравнивает значения переменных и возвращает результат, НО в случае со ссылочными типами данных (объекты, массивы и т.д.) сравнивает ссылки на объекты в памяти компьютера, и на основании равенства или неравенства ссылок возвращает результат (true или false). Вот в чём отличие метода equals и оператора ==.

Вы можете почитать подробную статью про оба вида типов данных и их различия в соответствующей статье.

Метод equals – это метод класса Object. Каждый объект неявно унаследован от класса Object и они могут вызывать метод equals.

Возвращаясь к примеру, приведенному в начале подраздела, можно сделать вывод о том, каким будет результат операции сравнения в обоих случаях:

Стоит понимать, что вместо класса String, мог быть объявлен любой другой ссылочный тип данных (Object, ArrayList<>, ваш пользовательский класс и т.д.).

Переопределение метода equals в Java

Когда же стоит переопределять метод equals? Это стоит делать только тогда, когда для вашего класса определено понятие логической эквивалентности, которая не совпадает с тождественностью объектов.

Например, для классов Integer и String данное понятие можно применить.

Переопределение метода equals нужно не только для того, чтобы удовлетворить ожидания программистов, оно также позволяет использовать экземпляры класса в качестве ключей в некой схеме или элементов в неком наборе, имеющих необходимое и предсказуемое поведение. Что это значит?

Давайте рассмотрим пример кода:

Мы создаем список объектов Address и добавляем объект класса Address с одинаковым конструктором. Добавляем данный объект 2 раза в List, и с помощью цикла удаляем его. Затем выводим в консоль длину списка.

После выполнения программы, в консоли отобразится число 2. Но почему же количество записей в списке не изменилось? Ведь мы пытались их удалить. В примере объекты с равными полями number и street, и всё-таки – почему они не удалились?

При удалении объектов из списка неявно вызывается метод equals и если объект который мы передаем для удаления содержится в списке, то он удаляется. Реализация equals в классе Object проверяет только равенство ссылок. А ссылки у экземпляров классов различные, потому что это совершенно разные объекты, каждый их них был создан с помощью оператора new. Как же это исправить? Необходимо переопределить метод equals в классе Address:

Запустим программу снова и увидим, что количество объектов в списке стало равным нулю.

Скачать исходник программы из этого урока, вы можете, нажав на кнопку ниже:

Скачать исходник

 

 

Правила переопределения метода equals в Java

Какие правила существуют для правильного переопределения метода equals? Их пять.

  • Рефлексивность: для каждого ненулевого объекта х выражение x.equals(x) должно возвращать логическое значение true.
  • Симметричность: для всех ненулевых объектов х и у выражение x.equals(y) должно возвращать значение true тогда и только тогда, когда y.equals(x) возвратит true.
  • Транзитивность: для всех трёх ненулевых объектов х, у и z, если х.equals(y) возвращает логическое true и у.equals(z) возвращает true, то и выражение х.equals(z) должно всегда возвращать true.
  • Непротиворечивость: если для всех ненулевых объектов х и у несколько раз вызвать х.equals(у), то всегда должно возвращаться значение true (либо false), при условии, что никакая информация,содержащаяся в объектах, не поменялась.
  • И последнее: для всех ненулевых х выражение х.equals(null) должно всегда возвращать логическое значение false.

Если у вас нет склонности к математике, то всё это выглядит страшным, не так ли? Но вчитайтесь несколько раз и разберитесь с вышесказанным. На самом деле всё очень просто. Данные правила нарушать нельзя. В противном случае вы рискуете обнаружить, что ваше приложение работает неустойчиво, неправильно или завершается с ошибкой, а установить источник ошибок такого класса крайне затруднительно.

 

Метод equals в Java
5 (100%) 6 votes

Поделиться в соц. сетях:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">