The main reason to (re)declare such a method, is to extend and document the contract. In case of Comparator.equals(…)
, it’s not that obvious, as it doesn’t specify so much news. It says
This method must obey the general contract of Object.equals(Object)
. Additionally, this method can return true
only if the specified object is also a comparator and it imposes the same ordering as this comparator. Thus, comp1.equals(comp2)
implies that sgn(comp1.compare(o1, o2))==sgn(comp2.compare(o1, o2))
for every object reference o1
and o2
.
which most people would have assumed anyway. Even worse, not overriding equals
is fine, if not to say the best way to enforce this contract, especially as the JRE classes never consider comparator equality anyway.
To get better examples of overriding methods, consider
List.equals(Object)
Returns true
if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal
. (Two elements e1
and e2
are equal if Objects.equals(e1, e2)
.)
…
List.hashCode()
Returns the hash code value for this list. The hash code of a list is defined to be the result of the following calculation:
int hashCode = 1;
for (E e : list)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
This ensures that list1.equals(list2)
implies that list1.hashCode()==list2.hashCode()
for any two lists, list1
and list2
, as required by the general contract of Object.hashCode()
.
This provides an extended contract that can not be fulfilled by simply using the equals(Object)
and hashCode()
methods inherited from java.lang.Object
. Unfortunately, an interface can not enforce its implementation classes to override these methods, but that shouldn’t stop it from declaring it to document the contract.
Of course, having such a contract would not be compatible with an intention of using an interface as functional interface, as lambda expressions and method references can not override methods inherited from java.lang.Object
to provide more specific implementations.
But java.util.Comparator
was introduced in Java?2, long before Java?8, which introduced the concept of functional interfaces. As said, it’s special in that we still can use Comparator
as functional interface, as the equals
implementation inherited from java.lang.Object
is fine regarding the contract specified for java.util.Comparator.equals
.
So when designing new interfaces intended to be used as functional interface, you should not declare methods matching those of java.lang.Object
.