2016-04-25 9 views
7

Die Definition einer funktionellen Schnittstelle in Java 8 sagt:Definition von Functional-Schnittstelle in Java 8

Eine funktionale Schnittstelle wie jede Schnittstelle definiert ist, die genau man explizit erklärte abstrakte Methode hat. (Die Qualifizierung ist notwendig, da eine Schnittstelle nicht abstrakte Standardmethoden haben kann.) Aus diesem Grund wurden Funktionsschnittstellen als Single Interfaces bezeichnet, die manchmal noch zu sehen sind.

Wie kommen wir haben dies:

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

Da die sort Methode in List ist:

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); 
     } 
    } 

Und der Lambda-Ausdruck sagt:

Lambda Expression sollte einer funktionalen Schnittstelle zuweisbar sein

Comparator Die Schnittstelle hat zwei abstrakte Methoden, die compare und equals sind und mit @FunctionalInterface annotiert. Verstößt dies nicht gegen die Definition einer funktionalen Schnittstelle mit nur einer abstrakten Methode?

+1

Jede Klasse in Java erbt von 'Object' und hat die impliziten Methoden' Object :: toString', 'Object :: equals',' Object :: hashCode'. Daher ist 'Comparator 'eine Schnittstelle mit einer SAM, die die implizite Methode überschreibt. – Flown

+0

Woher hast du diese Definition? – Tunaki

+0

Es gibt viele Blogs, in denen ich die Definition gelesen habe, die ich oben geteilt habe. Und gemäß den Richtlinien von stackoverflow kann ich den Link zu anderen Blogs nicht teilen. –

Antwort

14

Es stimmt, dass die Schnittstelle Comparator 2 abstrakte Methoden hat. Aber einer von ihnen ist equals, die die equals Methode überschreibt, die in der Object Klasse definiert wird, und diese Methode zählt nicht.

Von @FunctionalInterface:

Wenn eine Schnittstelle eine abstrakte Methode erklärt einer der öffentlichen Methoden java.lang.Object überschreiben, die auch tut nicht Zahl in Richtung der abstrakten Methode gräflichen Schnittstelle, da jede Implementierung der Schnittstelle haben eine Implementierung von java.lang.Object oder anderswo.

Als solches Dies macht die Comparator Schnittstelle eine funktionale Schnittstelle, wo die funktionale Methode compare(o1, o2) ist.

Der Lambda-Ausdruck (a, b) -> a > b ? -1 : 1 erfüllt diesen Vertrag: Er deklariert 2 Parameter und gibt eine int zurück.

+2

Und wenn wir dabei sind, sollte betont werden, dass diese Definition, anders als im Zitat der Frage behauptet, nicht erfordert, dass die abstrakte Methode explizit deklariert wird. – Holger

+2

Und es sollte erwähnt werden, dass, während dieser Lambda-Ausdruck der * Form * der Funktion entspricht und daher vom Compiler akzeptiert wird, er den * Vertrag * der 'Comparator'-Schnittstelle verletzt und zur Laufzeit ein willkürliches Chaos verursachen kann ... – Holger

+1

Ja, in diesem Fall wäre 'Comparator.reverseOrder()' eine bessere Wahl. – Tunaki