2008-08-19 2 views
19

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

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

ответ

19

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

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

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

EDIT: Я не отправлял это как полный ответ на эту тему, поэтому я эхо заявление Фредрика Kalseth, что наиважнейшая равно лучше работает для immutable objects. Цитирую API для Map:

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

+2

Глава 1 Эффективная глава Java (Джош Блох, 1-е изд.) По java.lang.Объектные методы: http://java.sun.com/developer/Books/effectivejava/Chapter3.pdf – McDowell 2009-04-30 16:51:29

0

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

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

0

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

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

См. here для получения полного пояснения.

8

Я очень рекомендую подбирать копию Эффективной Java и читать через пункт 7, подчиняясь equals contract. Вам нужно быть осторожным, если вы переопределяете равные для изменяемых объектов, так как многие из таких коллекций, как Карты и наборы, используют равные для определения эквивалентности, а мутация объекта, содержащегося в коллекции, может привести к неожиданным результатам. Брайан Goetz также имеет довольно хороший overview of implementing equals and hashCode.

4

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

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

0

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

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

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

2

@David Schlosnagle mentions упоминает Джош Блоха Effective Java - это должен прочитать для любого разработчика Java.

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

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