Я пытаюсь переопределить метод equals в Java. У меня есть класс, People
который в основном имеет 2 поля данных name
и age
. Теперь я хочу переопределить equals
метод, чтобы я мог проверять между двумя объектами People.
Мой код выглядит следующим образом
public boolean equals(People other){
boolean result;
if((other == null) || (getClass() != other.getClass())){
result = false;
} // end if
else{
People otherPeople = (People)other;
result = name.equals(other.name) && age.equals(other.age);
} // end else
return result;
} // end equals
Но когда я пишу, age.equals(other.age)
это дает мне ошибку, поскольку метод equals может сравнивать только String, а age - Integer.
Решение
Я использовал предложенный ==
оператор, и моя проблема решена.
java
overriding
equals
бобр
источник
источник
Ответы:
Вывод:
источник
hash = 53 * hash
почему вы используете это?getClass()
вызовет проблемы, если класс станет подклассом и будет сравниваться с объектом суперкласса.hashCode()
instanceof
оператора илиisAssignableFrom
. Для этого потребуется точное соответствие типа, а не соответствие подтипа. - Симметричное требование. Также для сравненияString
или других типов объектов вы можете использоватьObjects.equals(this.name,other.name)
.Введение новой сигнатуры метода, изменяющей типы параметров, называется перегрузкой :
Здесь
People
отличается отObject
.Когда сигнатура метода остается идентичной сигнатуре его суперкласса, это называется переопределением, и
@Override
аннотация помогает различать их во время компиляции:Не видя фактического объявления
age
, трудно сказать, почему возникает ошибка.источник
Я не уверен в деталях, поскольку вы не опубликовали весь код, но:
hashCode()
, аequals
метод должен иметьObject
, а не вPeople
качестве типа аргумента. В настоящий момент вы перегружаете, а не переопределяете метод equals, что, вероятно, не то, что вам нужно, особенно с учетом того, что вы проверите его тип позже.instanceof
чтобы проверить, что это объект People, напримерif (!(other instanceof People)) { result = false;}
equals
используется для всех объектов, но не для примитивов. Я думаю, вы имеете в виду возрастint
(примитив), и в этом случае просто используйте==
. Обратите внимание, что целое число (с большой буквы) - это объект, который следует сравнивать с равным.См. Какие вопросы следует учитывать при переопределении equals и hashCode в Java? Больше подробностей.
источник
источник
Пункт 10: Соблюдайте общий договор при переопределении равных
Каждый экземпляр класса уникален по своей сути . Это верно для таких классов, как Thread, которые представляют активные сущности, а не значения. Реализация equals, предоставляемая Object, имеет в точности правильное поведение для этих классов.
Классу нет необходимости предоставлять тест на «логическое равенство». Например, java.util.regex.Pattern мог бы переопределить equals, чтобы проверить, представляют ли два экземпляра Pattern одно и то же регулярное выражение, но дизайнеры не думали, что клиентам понадобится или захотят эта функциональность. В этих условиях реализация equals, унаследованная от Object, является идеальной.
Суперкласс уже переопределил равенство, и поведение суперкласса подходит для этого класса. Например, большинство реализаций Set наследуют свою реализацию equals от AbstractSet, реализации List от AbstractList и реализации Map от AbstractMap.
Класс является частным или частным для пакета , и вы уверены, что его метод equals никогда не будет вызван. Если вы крайне не склонны к риску, вы можете переопределить метод equals, чтобы гарантировать, что он не будет вызван случайно:
equals
Метод реализует отношение эквивалентности. Он имеет следующие свойства:Рефлексивный: Для любого эталонного значения ненулевого
x
,x.equals(x)
должно возвращать верно.Симметричный: Для любых эталонных значений ненулевых
x
иy
,x.equals(y)
должны вернуть истинно тогда и только тогда , когда y.equals (х) возвращает истину.Переходный: Для любых эталонных значений непустых
x
,y
,z
, еслиx.equals(y)
возвращаетсяtrue
иy.equals(z)
возвращаетсяtrue
, тоx.equals(z)
должен вернутьсяtrue
.Согласованный: для любых ненулевых ссылочных значений
x
иy
множественные вызовыx.equals(y)
должны последовательно возвращатьtrue
или последовательно возвращатьfalse
при условии, что никакая информация, используемая в равных сравнениях, не изменяется.Для любого эталонного значения ненулевым
x
,x.equals(null)
должен вернутьсяfalse
.Вот рецепт высококачественного метода равенства:
Используйте
==
оператор, чтобы проверить, является ли аргумент ссылкой на этот объект. Если да, верните true. Это всего лишь оптимизация производительности, но ее стоит сделать, если сравнение потенциально дорого.Используйте
instanceof
оператор, чтобы проверить, имеет ли аргумент правильный тип. Если нет, верните false. Как правило, правильный тип - это класс, в котором используется метод. Иногда этот класс реализует какой-то интерфейс. Используйте интерфейс, если класс реализует интерфейс, который уточняет контракт равенства, чтобы разрешить сравнения между классами, реализующими интерфейс. Это свойство есть у интерфейсов коллекций, таких как Set, List, Map и Map.Entry.Приведите аргумент к правильному типу. Поскольку этому приведению предшествовал тест instanceof, он гарантированно завершится успешно.
Для каждого «значимого» поля в классе проверьте, соответствует ли это поле аргумента соответствующему полю этого объекта. Если все эти тесты прошли успешно, верните true; в противном случае верните false. Если тип на шаге 2 является интерфейсом, вы должны получить доступ к полям аргумента через методы интерфейса; если тип является классом, вы можете получить доступ к полям напрямую, в зависимости от их доступности.
Для примитивных полей, тип которых не равен
float
илиdouble
, используйте==
оператор для сравнения; для полей ссылки на объект вызовитеequals
метод рекурсивно; дляfloat
полей используйте статическийFloat.compare(float, float)
метод; а дляdouble
полей используйтеDouble.compare(double, double)
. Специальная обработка поплавка и двойных полей стало необходимым существованиемFloat.NaN
,-0.0f
и аналогичных двойных значений; В то время как вы могли бы сравнитьfloat
иdouble
поля со статическими методамиFloat.equals
иDouble.equals
это повлекло бы за собой Autoboxing на каждое сравнение, который будет иметь низкую производительность. Дляarray
полей примените эти рекомендации к каждому элементу. Если каждый элемент в поле массива имеет значение, используйте один изArrays.equals
методов.Некоторые поля ссылки на объект могут законно содержать
null
. Чтобы избежать вероятности возникновения ошибкиNullPointerException
, проверьте такие поля на равенство с помощью статического методаObjects.equals(Object, Object)
.источник
hashCode()
. Также обратите внимание, что с момента написания Java7equals()
иhashCode()
методов стало намного проще с помощьюObjects.equals()
,Arrays.equals()
иObjects.hashCode()
,Arrays.hashCode()
.if (getClass() != obj.getClass()) ...
а не использования оператора instanceof. Для этого потребуется точное соответствие типа, а не соответствие подтипа. - Симметричное требование.Поскольку я предполагаю, что
age
это типint
:источник
NullPointerException
ifname
isnull
.name
никогда не присваиваетсяnull
значение ...При сравнении объектов в Java вы выполняете семантическую проверку , сравнивая тип и идентифицирующее состояние объектов с:
null
Правила:
a.equals(b) == b.equals(a)
equals()
всегда даетtrue
илиfalse
, но никогдаNullpointerException
,ClassCastException
или любой другой бросаемыйСравнение:
instanceof
для сравнения типов (что работает только до тех пор, пока нет подклассов, и нарушает правило симметрии, когдаA extends B -> a instanceof b != b instanceof a)
.Для вашего
Person
класса:Универсальный универсальный служебный класс многократного использования:
Для вашего
Person
класса, используя этот служебный класс:источник
если age является int, вы должны использовать ==, если это объект Integer, вы можете использовать equals (). Вам также необходимо реализовать метод хэш-кода, если вы переопределите equals. Подробная информация о контракте доступна в javadoc Object, а также на различных веб-страницах.
источник
Вот решение, которое я недавно использовал:
источник