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

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

Рассмотрим следующую Java-программу:

private double re, im;

public Complex( double re, double im) <

// Класс драйвера для тестирования класса Complex

public class Main <

public static void main(String[] args) <

Complex c1 = new Complex( 10 , 15 );

Complex c2 = new Complex( 10 , 15 );

System.out.println( "Not Equal " );

Причина вывода «Не равно» проста: когда мы сравниваем c1 и c2, проверяется, ссылаются ли оба c1 и c2 на один и тот же объект или нет ( переменные объекта всегда являются ссылками в Java ). c1 и c2 относятся к двум разным объектам, поэтому значение (c1 == c2) равно false. Если мы создадим еще одну ссылку, скажем, c3, как показано ниже, то (c1 == c3) даст true.

Complex c3 = c1; // (c3 == c1) будет верно

Итак, как мы проверяем равенство значений внутри объектов? Все классы в Java наследуются от класса Object прямо или косвенно (см. Пункт 1 этого ). Класс Object имеет несколько основных методов, таких как clone (), toString (), equals () и т. Д. Мы можем переопределить метод equals в нашем классе, чтобы проверить, имеют ли два объекта одинаковые данные или нет.

private double re, im;

public Complex( double re, double im) <

// Переопределение equals () для сравнения двух сложных объектов

public boolean equals(Object o) <

// Если объект сравнивается с самим собой, возвращаем true

/ * Проверить, является ли o экземпляром Complex или нет

«null instanceof [type]» также возвращает false * /

if (!(o instanceof Complex)) <

// приведем o к Complex, чтобы мы могли сравнивать элементы данных

Complex c = (Complex) o;

// Сравнить элементы данных и вернуть соответственно

return Double.compare(re, c.re) == 0

// Класс драйвера для тестирования класса Complex

public class Main <

public static void main(String[] args) <

Complex c1 = new Complex( 10 , 15 );

Complex c2 = new Complex( 10 , 15 );

System.out.println( "Not Equal " );

В качестве примечания, когда мы переопределяем equals (), рекомендуется также переопределить метод hashCode (). Если мы этого не сделаем, равные объекты могут получить разные хеш-значения; и коллекции на основе хешей, включая HashMap, HashSet и Hashtable, не работают должным образом (см. это для более подробной информации). Подробнее о hashCode () мы расскажем в отдельном посте.

Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

Я пытаюсь переопределить метод equals в java. У меня есть класс людей, который в основном имеет 2 поля данных имя и возраст. Теперь я хочу переопределить метод equals, чтобы я мог проверять объекты 2 People.

мой код выглядит следующим образом

но когда я пишу возраст.равно (другое.возраст) это дает мне ошибку, так как метод equals может сравнивать только строку, а возраст-целое число.

пожалуйста, помогите мне исправить это.

I используется = = оператор, как было предложено, и моя проблема решена. Спасибо всем, что приложили усилия, чтобы помочь мне.

9 ответов

выход:

— Subash Adhikari-VS-K false

— Subash Adhikari-VS-StackOverflow false

— Subash Adhikari-VS-Subash adhikari true

— K — VS-StackOverflow false

— K — VS-Subash adhikari false

— StackOverflow-VS-Subash adhikari false

— BUILD успешно (общее время: 0 секунд)

прежде всего: вы не переопределение equals , вы перегрузка его.

не видя фактического объявления age трудно сказать, почему вы получаете ошибку.

Я не уверен в деталях, поскольку вы не опубликовали весь код, но:

  • не забудьте переопределить hashCode() а также
  • the equals метод должен иметь Object , а не People в качестве типа аргумента. В данный момент вы перегружаете, а не переопределяете метод equals, который, вероятно, не является тем, что вы хотите, особенно учитывая, что вы проверяете его тип позже.
  • можно использовать instanceof чтобы проверить, что это объект People, например if (!(other instanceof People))
  • equals используется для всех объектов, но не для примитивов. Я думаю, вы имеете в виду возраст int (примитивный), в этом случае просто используйте == . Обратите внимание, что целое число (с заглавной "I") — это объект, который следует сравнивать с равными.
Читайте также:  При наведении на картинку появляется текст css

Так как я предполагаю age типа int :

пункт 10: соблюдать генеральный контракт при переопределении равно

согласно эффективному Java, переопределение equals метод кажется простым, но есть много способов ошибиться, и последствия могут быть ужасными. Самый простой способ избежать проблем — не переопределять equals метод, в этом случае каждый экземпляр класса равен только самому себе. Это правильно, если любое из следующих условий применить:

каждый экземпляр класса по своей сути уникален. Это верно для таких классов, как поток, которые представляют активные сущности, а не значения. Реализация equals, предоставляемая Object, имеет точно правильное поведение для этих классов.

нет необходимости в том, чтобы класс предоставлял тест "логического равенства". например, java.утиль.регулярное выражение.Pattern мог переопределить equals чтобы проверить, представляют ли два экземпляра шаблона одно и то же регулярное выражение, но дизайнеры не думали, что клиенты будут нуждаться или хотят эту функциональность. В этих условиях реализация equals, унаследованная от Object, является идеальной.

суперкласс уже переопределил equals, и поведение суперкласса подходит для этого класса. Например, большинство реализаций Set наследуют реализацию equals от AbstractSet, список реализаций из AbstractList и реализации Карты из AbstractMap.

класс является частным или package-private, и вы уверены, что его метод equals никогда не будет вызван. Если вы очень не склонны к риску, вы можете переопределить метод equals, чтобы убедиться, что он не вызывается случайно:

на equals метод реализует отношение эквивалентности. Он имеет свойства:

Reflexive: для любого ненулевого опорного значения x , x.equals(x) должен возвращать true.

Symmetric: для любых ненулевых опорных значений x и y , x.equals(y) должен возвращать true тогда и только тогда, когда y.equals (x) возвращает true.

Transitive: для любых ненулевых опорных значений x , y , z , если x.equals(y) возвращает true и y.equals(z) возвращает true , потом x.equals(z) должны возвращение true .

Consistent: для любых ненулевых ссылочных значений x и y , несколько вызовов x.equals(y) должен последовательно возвращать true или последовательно возвращать false , при условии, что не изменяется информация, используемая в сравнениях equals.

для любого ненулевого опорного значения x , x.equals(null) должен возвратить false .

вот рецепт для высококачественных равных метод:

использовать == оператор, чтобы проверить, является ли аргумент ссылкой на этот объект. Если это так, верните true. Это просто оптимизация производительности, но это стоит сделать, если сравнение потенциально дорого.

использовать instanceof оператор, чтобы проверить, имеет ли аргумент правильный тип. Если нет, то вернуть false. Как правило, правильный тип-это класс, в котором происходит метод. Иногда это какой-то интерфейс реализовано этим классом. Используйте интерфейс, если класс реализует интерфейс, который уточняет контракт equals, чтобы разрешить сравнения между классами, реализующими интерфейс. Интерфейсы коллекции, такие как Set, List, Map и Map.Вход есть это свойство.

приведите аргумент к правильному типу. Поскольку этому приведению предшествовал тест instanceof, он гарантированно будет успешным.

для каждого "значимого" поля в классе, проверьте, совпадает ли это поле аргумента с соответствующим полем данного объекта. Если все эти тесты успешно, возвращает true; в противном случае возвращает false. Если тип в шаге 2 является интерфейсом, необходимо получить доступ к полям аргумента с помощью методов интерфейса; если тип является классом, можно получить доступ к полям напрямую, в зависимости от их доступности.

для примитивных полей, тип которых не float или double используйте == оператор сравнения; для полей ссылки на объект вызовите equals метод рекурсивно; для float поля, используйте static Float.compare(float, float) способ; и double поля, используйте Double.compare(double, double) . Специальная обработка поплавковых и двойных полей обусловлена существованием Float.NaN , -0.0f и аналогичные двойные значения; в то время как вы могли бы сравнить float и double поля со статическими методами Float.equals и Double.equals , это повлечет автобоксинг на каждом сравнении, которое имело бы плохую производительность. Для array поля, примените эти рекомендации к каждому элементу. Если каждый элемент в поле массива является значительным, использовать Arrays.equals методы.

Читайте также:  Схема ночника с датчиком света

некоторые поля ссылок на объекты могут законно содержать null . Чтобы избежать возможности NullPointerException , проверьте такие поля на равенство с помощью статического метода Objects.equals(Object, Object) .

при сравнении объектов в Java вы делаете семантические проверки сравнение тип и определение состояния объекты:

  • сам (тот же экземпляр)
  • сам (клон, или реконструированная копия)
  • другие объекты различных типов
  • другие объекты того же типа
  • null
  • симметрия: a.equals(b) == b.equals(a)
  • equals() всегда дает true или false , а не NullpointerException , ClassCastException или любой другой throwable
  • введите check: оба экземпляра должны быть то же самое тип, то есть вы должны сравнить фактические классы для равенства. Это часто не правильно реализовано, когда разработчики используют instanceof для сравнения типов (который работает только до тех пор, пока нет подклассов, и нарушает правило симметрии, когда A extends B -> a instanceof b != b instanceof a) .
  • семантическая проверка идентифицирующего состояния: убедитесь, что вы понимаете, в каком состоянии идентифицируются экземпляры. Лица могут быть идентифицированы по номеру социального страхования, но не по цвету волос (могут быть окрашены), имени (могут быть изменены) или возрасту (все время меняется). Только с объектами value следует сравнивать полное состояние (все нестационарные поля), в противном случае проверяйте только то, что идентифицирует экземпляр.

для Person класс:

многоразовый, общий класс полезности:

для Person класс, используя этот класс утилиты:

Если age-int, вы должны использовать == если это целочисленный объект, то вы можете использовать equals (). Вам также необходимо реализовать метод hashcode, если вы переопределяете equals. Подробности контракта доступны в javadoc объекта, а также на различных страницах в интернете.

метод equals определяет параметр метода типа Object, а его возвращаемый тип-boolean.

при определении (переопределить) этот метод в вашем классе для сравнения двух объектов.

Для начала. Объекты в java могут быть между собой равны, а могут быть эквивалентны

1) равными(через знак ==) могут быть только ссылки, не объекты.
2) эквивалентными называются объекты с одинаковыми значениями полей
но equals != эквивалентность
объясним почему:

hashcode()

hashcode() – метод Object, возвращающий int значение.

В классе Object метод hashCode() определен как public native int hashCode();
исходный код hashCode() написан на другом языке.
Алгоритм генерации хешкода для объекта работает с учаcтием генератора случайных чисел, то есть при каждом выполнении программы хеш-коды объектов будут разными

Однако следует пристально обратить внимание на одно разительное несовершенство функции hashCode():
Если хешкоды объектов не равны, то объекты гарантированно разные. Но, неверно обратное,- если хешкоды объектов равны, то и сами объекты равны.
Ситуация, когда у разных объектов появляются одинаковые хешкоды называется коллизией.
A – хешкод x равен хешкоду y
B – x = y
1) -A -> -B если хешкоды объектов неравны, то объекты неравны
2) -(A -> B) неверно, что если хешкоды равны, то объекты равны
таким образом
(-A -> -B) & (-(A -> B))
(-A / B) & (-(A / -B))
(-A / B) & (-A / B)
получаем две истины
-A / B
1) хешкоды неравны, и объекты неравны
2) хешкоды равны, объекты неравны
3) хешкоды равны, объекты равны

-A / B и есть ситуация коллизии, хешкоды неравны, но объекты равны

equals()

В идеале етод equals() класса Object должен проверять объекты на эквивалентность, исходная же реализация метода equals в классе Object

equals() тупо сравнивает ссылки (ссылки на адреса памяти зарезервированные под объекты), и если они ссылаются на один и тот же объект, возвращает true
equals() не сравнивает значения полей объектов!

Резюмируем:
Итак мы выяснили, что стандартная реализация методов equals() и hashCode() предоставляет из себя весьма скудный и абстрактный инструментарий. Hashcode() выдает нам не всегда уникальный int, а equals по умолчанию, не сравнивает значения полей объекта, а реализован в виде простого ссылочного сравнения.

Читайте также:  Как переконвертировать файл pdf в word

В чем проблема equals() и hashСode() и зачем их нужно переопределять?

Джошуа Блох в книге “Эффективное программирование” писал так, –
“Переопределяя метод equals() всегда переопределяйте hashCode()”

эээ.. так а в чем проблема? В чем проблема equals() и hashcode() и зачем их нужно переопределять? по умолчанию. инструментарий java не обеспечивает алгоритма сравнения объектов на предмет равенства за исключением сравнения ссылок на адреса разделов памяти, зарезервированных под объекты. Так же, по умолчанию java не гарантирует безупречную(полностью удовлетвлряющую требованиям) работу по идентификации объектов с помощью хешкодов. Иными словами, по умолчанию сравнение объектов в java осуществляется сравнением ссылок на адреса памяти. Но проблема в том, что многие важные инструменты java, такие, как инфраструктура коллекций, переопределяют метод для сравнения equals, используя при этом метод hashcode*. Таким образом, если мы не уделяем внимания объектам(не переопределяем вышеназванные методы), которые могут содержаться в этих типах коллекций, мы подспудно, сами того не осознавая, закладываем в код потенциальную возможность ошибок, связанных с несовершенством этих методов.
Например, мы создаем большую HashMap. Так как хешкод по умолчанию может выдавать одинаковые int-ы, то каждый раз когда мы захотим положить объект в hashmap() ( с помощью put())а его хеш вдруг случайно совпадет с хешем уже существующего в мэпе объекта**(так как ключами в HashMap е являются хеши), то мы не добавим новый объект а просто перетрем значение старого новым значением! Вот так, незатейливо произойдет ошибка.

Переопределяем equals()

Итак, по умолчанию, “равенства” объектов как таковых в java нет. Равными могут быть ссылки. Равенство ссылок означает, что они ссылаются на один и тот же объект.
Однако, правило равенства между объектами одного типа, для того, чтобы их можно было сравнивать, можно написать самому. Что и настоятельно следует делать, переопределяя метод equals()! Вспомним сейчас, что если мы переопределяем equals() то нам также следует переопределить и hashCode, ибо как и было рассказано в предыдущем абзаце, многие важные классы пользуются equals() и hashCode().

I. Самый простой способ реализовать equals() и hashCode() в своем классе, воспользоваться авто-генерацией через IDE. Например, в JIdea это можно сделать с помощью alt + insert.

Также есть ряд требований и рекомендаций к реализации equals() и hashCode()

Реализация equals() должна обладать тремя важными свойствами бинарных отношений
1) рефлексивность: a.equals(a)=true;
2) симметричность: if((a.equals(b)))
3) транзитивность: if((a.equals(b))&&(b.equals(c)))
4) equals() должна возвращать неизменное значение, пока какое-либо из свойств объектов не изменяется.
Пока свойства объектов остаются неизменными, они должны оставаться равны.
4) Повторные вызовы метода equals() должны возвращать одно и тоже значение до тех пор, пока какие-либо значения свойств объекта не будут изменены. То есть, если два объекта равны в Java, то они будут равны пока их свойства остаются неизменными.
5) Необходимо проверять объект на null. В случае, если объект = null, equals() должен возвраoать false, а не выкидывать исключение.
6) не помешает проверка соответствия типа(для этого следует использовать getClass())
7) необходимо привести в соответствие equals() и compareTo() для корректной работы hash-коллекций.***

Резюме

a.hashCode() != b.hashCode() -> !(a.equals(b))
a.hashCode() = b.hashCode() -> ((a.equals(b)) / !(a.equals(b)))
Что вносит ущербность в реализацию некоторых коллекций****, основные алгоритмы которых(алгоритмы проверки объектов на предмет равенства) основаны на функциях equals() и hashCode().
Посему в случае, если объекты, планируется содержать в коллекциях, методы которых основаны на данных алгоритмах, рекомендуется переопределять эти методы и приводить их в соответствие бизнес-логике программы

Примечания

**механизм put() класса HashMap несколько сложнее, HashMap содержит массив объектов Enrty, связанный список
***Распространенные ошибки при переопределении equals в Java
****В первую очередь, это коллекции HashSet и HashMap

Ссылка на основную публикацию
Очисти историю нашего разговора
На протяжении долгого времени Skype удерживает позиции лидера на рынке приложений для виртуального общения. Сегодня эта программа для видеочатов доступна...
Обновление видеокарты н видео
Driver Forum Automatic Driver Updates GeForce Experience automatically keeps your drivers up to date and your games super optimized. Learn...
Обновление для времени windows 7 x64
С 30 октября 2011 ненужно переводить часы. Чтобы привести работу Windows машин в соответствие с законом, нужно установить небольшие патчи....
Очиститель воздуха iqair healthpro 150
Оглавление Паспортные характеристики, комплект поставки и цена Название моделиHealthPro 250 NEТипочиститель воздухаЦветсветло-серый/белыйУправлениемеханические кнопки на корпусе и ИК-пульт ДУМощность электрическаяот 20...
Adblock detector