Переопределение метода equals против создания нового метода

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

Каковы аргументы за и против переопределения метода equals?

19.08.2008 17:05:26
7 ОТВЕТОВ
РЕШЕНИЕ

Переопределение метода equals необходимо, если вы хотите проверить эквивалентность в стандартных классах библиотек (например, обеспечить, чтобы java.util.Set содержал уникальные элементы или использовать объекты в качестве ключей в объектах java.util.Map).

Обратите внимание: если вы переопределяете equals, убедитесь, что вы выполняете контракт API, как описано в документации. Например, убедитесь, что вы переопределяете Object.hashCode :

Если два объекта равны в соответствии с методом equals (Object), то вызов метода hashCode для каждого из двух объектов должен привести к одному и тому же целочисленному результату.

РЕДАКТИРОВАТЬ: я не опубликовал это как полный ответ на эту тему, поэтому я повторю утверждение Фредрика Калсета о том, что переопределение равно лучше всего подходит для неизменных объектов . Чтобы процитировать API для карты :

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

19
19.08.2008 17:39:44
Глава «Эффективная Java» (Джош Блох; 1-е изд.), Посвященная
McDowell 30.04.2009 16:51:29

Метод Equals предназначен для сравнения ссылок. Поэтому не следует переопределять его поведение.

Вы должны создать новый метод для проверки эквивалентности в различных случаях, если вам нужно (или использовать метод CompareTo в некоторых классах .NET)

0
19.08.2008 17:08:39

Вам нужно только переопределить equals()метод, если вы хотите, чтобы определенное поведение при добавлении объектов в отсортированные структуры данных ( SortedSetи т. Д.)

Когда вы делаете это, вы также должны переопределить hashCode().

Смотрите здесь для полного объяснения.

0
15.12.2014 17:04:19

Я настоятельно рекомендую взять копию Effective Java и прочитать пункт 7, соблюдая контракт «Равно» . Необходимо соблюдать осторожность, если вы переопределяете equals для изменяемых объектов, так как многие коллекции, такие как Карты и Наборы, используют equals для определения эквивалентности, а изменение объекта, содержащегося в коллекции, может привести к неожиданным результатам. Брайан Гетц также имеет довольно хороший обзор реализации equals и hashCode .

8
19.08.2008 17:26:53

Вы должны «никогда» не переопределять equals & getHashCode для изменяемых объектов - это относится как к .net, так и к Java. Если вы это сделаете и будете использовать такой объект в качестве ключа в f.ex словаре, а затем измените этот объект, у вас возникнут проблемы, потому что словарь использует хеш-код для поиска объекта.

Вот хорошая статья на эту тему: http://weblogs.asp.net/bleroy/archive/2004/12/15/316601.aspx

4
19.08.2008 17:28:02

Честно говоря, в Java на самом деле нет аргумента против переопределения равных . Если вам нужно сравнить случаи на равенство, то это то, что вы делаете.

Как упомянуто выше, вам нужно знать о контракте с hashCode и аналогичным образом следить за ошибками вокруг интерфейса Comparable - почти во всех ситуациях вы хотите, чтобы естественное упорядочение, как определено в Comparable, было согласовано с равными (см. BigDecimal api doc для примера канонического счетчика)

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

0
19.08.2008 21:12:50

@ Дэвид Шлоснагл упоминает, что упоминает « Эффективную Java» Джоша Блоха - это необходимо прочитать любому разработчику Java.

Существует связанная проблема: для объектов с неизменяемыми значениями вы также должны рассмотреть возможность переопределения compare_to. Стандартная формулировка, если они различаются, в Comparable API :

Обычно это так, но не обязательно, чтобы (сравните (x, y) == 0) == (x.equals (y)). Вообще говоря, любой компаратор, который нарушает это условие, должен четко указывать этот факт. Рекомендованный язык: «Примечание: этот компаратор налагает порядок, который несовместим с равными».

2
23.05.2017 11:46:50