Переопределение метода equals против создания нового метода - PullRequest
19 голосов
/ 19 августа 2008

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

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

Ответы [ 7 ]

19 голосов
/ 19 августа 2008

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

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

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

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

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

8 голосов
/ 19 августа 2008

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

4 голосов
/ 19 августа 2008

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

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

2 голосов
/ 20 августа 2008

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

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

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

0 голосов
/ 19 августа 2008

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

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

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

0 голосов
/ 19 августа 2008

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

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

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

0 голосов
/ 19 августа 2008

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...