Java. Сравнение объектов с оператором equals()

Существует два способа сравнить объекты в языке Java:

Сравнить объекты оператором equals() можно следующим образом:

Метод equals() принадлежит типу Object , который является предком каждого класса в языке Java. Это означает, что любой созданный вами класс будет наследовать базовое поведение equals() от Object . Это базовое поведение не отличается от оператора == . Другими словами, по умолчанию эти два выражения используют оператор == и возвращают значение false :

Посмотрите на метод spendMoney() класса Adult снова. Что происходит за кулисами, когда мы вызываем метод contains() нашей переменной wallet ? Язык Java использует оператор == для сравнения объектов в списке с указанным объектом. Если он находит соответствие, метод возвращает значение true ; в противном случае возвращается false . Поскольку мы сравниваем примитивы, он может найти соответствие, основанное на целочисленных значениях (помните, что оператор == сравнивает примитивы по их значению).

Это хорошо для примитивов, но что если мы хотим сравнить содержимое объектов? Оператор == не сделает это. Для сравнения содержимого объектов мы должны перегрузить метод equals() класса, экземпляром которого является переменная a . Это означает, что нужно создать метод с точно такой же сигнатурой, что и у метода одного из ваших суперклассов, но реализовать метод по другому. Если сделать это, вы сможете сравнивать содержимое двух объектов, а не только проверять, ссылаются ли две переменные на один и тот же экземпляр.

Попробуйте ввести следующий код в метод main() и взгляните на результат, отображаемый в консоли:

Первое сравнение возвращает значение false , поскольку adult1 и adult2 ссылаются на разные экземпляры Adult . Второе сравнение тоже возвращает значение false , поскольку реализация метода equals() по умолчанию просто проверяет, ссылаются ли обе переменные на один и тот же экземпляр. Но поведение equals() по умолчанию обычно не то, что мы хотим. Мы хотели бы сравнивать содержимое двух объектов Adult , чтобы узнать, одинаковые ли они. Для этого мы можем перегрузить equals() . Как видно из двух последних сравнений в приведенном выше примере, класс Integer перегружает метод так, что оператор == возвращает false , но оператор equals() сравнивает на равенство упакованные значения int . Мы сделаем что-то похожее для класса Adult в следующем разделе.

Перегрузка equals()

Перегрузка метода equals() для сравнения объектов на самом деле требует от нас перегрузки двух методов:

Мы перегрузим метод equals() следующим способом, который является обычным стилем в Java:

  • Если объект, который мы собираемся сравнивать, является самим этим объектом, то они очевидно равны, поэтому возвращаем true .
  • Проверяем для уверенности, что объект, который мы собираемся сравнивать, является экземпляром Adult (если нет, два объекта очевидно не одинаковы).
  • Приводим тип входного объекта к Adult , для того чтобы использовать его методы.
  • Сравниваем части двух объектов Adult , которые должны быть равны, для того чтобы два объекта считались «равными» (какое бы определение равенства мы ни использовали).
  • Если какие-либо из этих частей не равны, возвращаем значение false ; в противном случае возвращаем true .

Обратите внимание на то, что мы можем сравнить возраст каждого объекта с помощью == , поскольку это примитивные значения. Для сравнения String мы используем equals() , поскольку этот класс перегружает метод equals() для сравнения содержимого объектов String (если бы мы использовали == , то получали бы false каждый раз, потому что два объекта String никогда не будут одним и тем же объектом). То же самое мы делаем и для ArrayList , поскольку он перегружает equals() для проверки того, что два списка содержат одинаковые элементы в одинаковом порядке. Это хорошо подходит для нашего простого примера.

Когда бы вы ни перегрузили equals() , необходимо также перегрузить hashCode() . Объяснение причины этого выходит за рамки данного руководства, а пока просто знайте, что язык Java использует значение, возвращенное из этого метода, для помещения экземпляров вашего класса в коллекции, которые используют хэш-алгоритм размещения объектов (например HashMap ). Единственными практическими правилами для этого метода (кроме того, что он должен возвращать целое значение) являются два приведенные далее правила. Метод hashCode() должен возвращать:

  • Одно и то же значение для одного и того же объекта постоянно.
  • Одинаковые значения для одинаковых объектов.

Как правило, возврат значений хэш-кода для некоторых или всех переменных экземпляра объекта является достаточно хорошим способом вычисления хэш-кода. Другим вариантом является преобразование переменных в объекты String , объединение их и возврат хэш-кода для полученного объекта String . Еще одним вариантом является умножение одной или нескольких числовых переменных на некоторую константу для дальнейшего обеспечения уникальности, но это часто излишне.


Похожие записи:

Leave a Reply

Your email address will not be published. Required fields are marked *