4

I found following code, What is use of inherited equals() and toString() method.

@FunctionalInterface
public interface  FunInterface<T> {
   // An  abstract method  declared in the functional interface 
   int test(T  o1,   T  o2);

   // Re-declaration of the equals() method in the Object class 
   boolean equals(Object  obj);

   String toString();
}
Naman
  • 27,789
  • 26
  • 218
  • 353
Raj N
  • 249
  • 1
  • 18

2 Answers2

7

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.

Holger
  • 285,553
  • 42
  • 434
  • 765
1

I see no point in this, since you can't really override them. For example you can override a default method to become abstract:

interface First {
    public default void go() {

    }
}

interface Second extends First {
    @Override
    public void go();
}

And any class implementing Second will be forced to implement go, unless it is of course abstract too.

It looks like someone thought about forcing every implementor of FunInterface to implement hashCode/equals too - but that would not work either.

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • Then why java.util.Comparator (i.e. functional interface ) inherited equals() method. – Raj N Jun 05 '18 at 09:29
  • 1
    @RajN believe or not - some people still think that this was a mistake, as the `Comparator` does not need this method at all. It is there just to specify a *specific* `javadoc` regarding `Comparator`s. Also notice that `Collection` has `equals` also - for the same reason (if this is a reason at all) – Eugene Jun 05 '18 at 09:40
  • 1
    @Eugene in case of `Collection`, it’s debatable, but for `List`, `Set`, and `Map`, it’s justified, as that’s the right place to define the contract, even if interfaces can’t enforce the implementors not to use the methods ingerited from `java.lang.Object`. By the way, believe it or not, regarding `Comparator.equals`, there is even an [actual, conforming implementation](https://docs.oracle.com/javase/9/docs/api/java/text/Collator.html#equals-java.lang.Object-). Not that it has much practical relevance. – Holger Jun 05 '18 at 10:58
  • I think the equals method in List, Set and other collections have nothing to do with the Objects equals method, although the end purpose might be same they are not overridden methods. Even the Collection interfaces equals documentaion says the same (While the Collection interface adds no stipulations to the general contract for the Object.equals). – raj240 Feb 26 '21 at 18:06