7

The definition of a functional Interface in Java 8 says:

A functional interface is defined as any interface that has exactly one explicitly declared abstract method. (The qualification is necessary because an interface may have non-abstract default methods.) This is why functional interfaces used to be called Single Abstract Method (SAM) interfaces, a term that is still sometimes seen.

So how come we have this:

List<Double> temperature = 
   new ArrayList<Double>(Arrays.asList(new Double[] { 20.0, 22.0, 22.5 }));
temperature.sort((a, b) -> a > b ? -1 : 1);

As the sort method in List is:

default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }

And the lambda expression says:

Lambda Expression should be assignable to a Functional Interface

The Comparator interface has two abstract methods which are compare and equals and is annotated with @FunctionalInterface. Does not this violate the definition of a functional interface having only one abstract method?

Tunaki
  • 132,869
  • 46
  • 340
  • 423
Deepak Kumar
  • 843
  • 1
  • 7
  • 19
  • 1
    Every class in Java inherits from `Object` and has the implicit methods `Object::toString`, `Object::equals`, `Object::hashCode`. Therefore `Comparator` is an interface with a SAM which overrides the implicit method. – Flown Apr 25 '16 at 15:13
  • Where did you get that definition? – Tunaki Apr 25 '16 at 15:21
  • There are a lot of blogs where I read the definition which I shared above. And as per the guidelines of stackoverflow I cannot share the link to other blogs.. – Deepak Kumar Apr 25 '16 at 15:34
  • 2
    Don’t base your knowledge on Blogs. There is [enough](https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html) [official](http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html) [material](https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.8) to study. You may use 3rd party tutorials and blogs, but if they cause confusion, verify with the official sources. – Holger Apr 25 '16 at 17:25

1 Answers1

14

It is true that the Comparator interface has 2 abstract methods. But one of them is equals, which overrides the equals method defined in the Object class, and this method doesn't count.

From @FunctionalInterface:

If an interface declares an abstract method overriding one of the public methods of java.lang.Object, that also does not count toward the interface's abstract method count since any implementation of the interface will have an implementation from java.lang.Object or elsewhere.

As such, this makes the Comparator interface a functional interface where the functional method is compare(o1, o2).

The lambda expression (a, b) -> a > b ? -1 : 1 complies with that contract: it declares 2 parameters and return an int.

Tunaki
  • 132,869
  • 46
  • 340
  • 423
  • 2
    And if we are at it, it should be emphasized that this definition, unlike claimed in the question’s quote, does not require the abstract method to be declared explicitly. – Holger Apr 25 '16 at 17:30
  • 2
    And it should be mentioned that, while this lambda expression complies with the *shape* of the function and hence is accepted by the compiler, it is violating the *contract* of the `Comparator` interface and can cause an arbitrary mess at runtime… – Holger Apr 25 '16 at 17:33
  • 1
    Yes, in this case `Comparator.reverseOrder()` would be a better choice. – Tunaki Apr 25 '16 at 17:48