Основной причиной (пере) объявления такого метода является продление и документирование договора.В случае Comparator.equals(…)
это не так очевидно, так как не указывает так много новостей.Там написано
Этот метод должен подчиняться генеральному контракту Object.equals(Object)
.Кроме того, этот метод может возвращать true
только , если указанный объект также является компаратором и на него накладывается тот же порядок, что и у этого компаратора.Таким образом, comp1.equals(comp2)
подразумевает, что sgn(comp1.compare(o1, o2))==sgn(comp2.compare(o1, o2))
для каждого объекта ссылается o1
и o2
.
, что большинство людей в любом случае предположило бы.Хуже того, не стоит переопределять equals
, если не сказать, что это лучший способ обеспечить соблюдение этого контракта, тем более что классы JRE никогда не учитывают равенство компараторов.
Чтобы получить лучшие примеры переопределенных методов, рассмотрим
List.equals(Object)
Возвращает true
тогда и только тогда, когда указанный объект также является списком, оба списка имеют одинаковый размер и все соответствующие пары элементов в двух спискахequal
.(Два элемента e1
и e2
равны, если Objects.equals(e1, e2)
.)
…
List.hashCode()
Возвращает хэш-кодзначение для этого списка.Хеш-код списка определяется как результат следующих вычислений:
int hashCode = 1;
for (E e : list)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
Это гарантирует, что list1.equals(list2)
подразумевает list1.hashCode()==list2.hashCode()
для любых двух списков, list1
и list2
,в соответствии с общим договором Object.hashCode()
.
Это предусматривает расширенный договор, который не может быть выполнен простым использованием методов equals(Object)
и hashCode()
, унаследованных от java.lang.Object
.К сожалению, интерфейс не может принудить свои классы реализации переопределить эти методы, но это не должно помешать ему объявить его для документирования контракта.
Конечно, наличие такого контракта не будет совместимымс намерением использовать интерфейс как функциональный интерфейс , поскольку лямбда-выражения и ссылки на методы не могут переопределять методы, унаследованные от java.lang.Object
, для обеспечения более конкретных реализаций.
Но java.util.Comparator
было введенов Java 2, задолго до Java 8, где была введена концепция функциональных интерфейсов.Как уже было сказано, особенность в том, что мы все еще можем использовать Comparator
в качестве функционального интерфейса, поскольку реализация equals
, унаследованная от java.lang.Object
, подходит для контракта, указанного для java.util.Comparator.equals
.
Так что при разработке новогоинтерфейсы, предназначенные для использования в качестве функционального интерфейса , не следует объявлять методы, соответствующие java.lang.Object
.