In Java 8 bin ich auf einen neuen Begriff gestoßen: "Funktionsschnittstelle". Ich konnte nur eine Verwendung finden, während ich mit Lambda-Ausdrücken arbeitete .
Java 8 bietet einige integrierte Funktionsschnittstellen. Wenn wir eine Funktionsschnittstelle definieren möchten, können wir die @FunctionalInterface
Anmerkung verwenden. Damit können wir nur eine einzige Methode in der Schnittstelle deklarieren.
Beispielsweise:
@FunctionalInterface
interface MathOperation {
int operation(int a, int b);
}
Wie nützlich ist es in Java 8, außer nur mit Lambda-Ausdrücken zu arbeiten ?
(Die Frage hier unterscheidet sich von der, die ich gestellt habe. Sie fragt, warum wir funktionale Schnittstellen benötigen, wenn wir mit Lambda-Ausdrücken arbeiten. Meine Frage lautet: Warum haben funktionale Schnittstellen neben Lambda-Ausdrücken auch andere Verwendungsmöglichkeiten?)
Antworten:
@FunctionalInterface
Anmerkungen sind nützlich, um die Kompilierungszeit Ihres Codes zu überprüfen. Sie können nicht mehr als eine Methode haben nebenstatic
,default
und abstrakte Methoden außer Kraft Methoden inObject
Ihrer@FunctionalInterface
oder jede andere Schnittstelle als funktionale Schnittstelle verwendet.Sie können jedoch Lambdas ohne diese Annotation verwenden und Methoden ohne
@Override
Annotation überschreiben .Aus Dokumenten
Dies kann im Lambda-Ausdruck verwendet werden:
Dies kann nicht im Lambda-Ausdruck verwendet werden:
Dies führt jedoch zu einem Kompilierungsfehler :
quelle
java.lang.Object
in einer funktionalen Schnittstelle nicht überschreibt .public
Methode außerstatic
und zu habendefault
“…Die Dokumentation macht in der Tat einen Unterschied zwischen dem Zweck
und der Anwendungsfall
deren Wortlaut andere Anwendungsfälle im Allgemeinen nicht ausschließt. Da der Hauptzweck darin besteht, eine funktionale Schnittstelle anzugeben, lautet Ihre eigentliche Frage: "Gibt es andere Anwendungsfälle für funktionale Schnittstellen als Lambda-Ausdrücke und Methoden- / Konstruktorreferenzen?"
Da die funktionale Schnittstelle ein Java-Sprachkonstrukt ist, das durch die Java-Sprachspezifikation definiert ist, kann nur diese Spezifikation diese Frage beantworten:
JLS §9.8. Funktionsschnittstellen :
Die Java-Sprachspezifikation sagt also nichts anderes aus. Der einzige in diesem Abschnitt erwähnte Anwendungsfall ist das Erstellen von Schnittstelleninstanzen mit Methodenreferenzausdrücken und Lambda-Ausdrücken. (Dies schließt Konstruktorreferenzen ein, da sie in der Spezifikation als eine Form des Methodenreferenzausdrucks angegeben sind.)
Also in einem Satz, nein, es gibt keinen anderen Anwendungsfall dafür in Java 8.
quelle
public static String generateTaskId()
, anstatt es "funktionaler" zu machen , wenn jemand anderes es wiepublic class TaskIdSupplier implements Supplier<String>
bei derget
Methode mit der Methode geschrieben hat bestehende Generationsimplementierung. Ist das ein Missbrauch von Funktionsschnittstellen, insbesondere die Wiederverwendung derSupplier
aus dem JDK integrierten? PS: Ich könnte keinen besseren Ort / Fragen und Antworten finden, um dies zu fragen. Gerne migrieren, wenn Sie vorschlagen könnten.TaskIdSupplier
. Die Frage ist nun, warum Sie die benannte Klasse erstellt haben. Es gibt Szenarien, in denen ein solcher benannter Typ benötigt wird, z. B. wenn Sie das Auffinden der Implementierung über unterstützen möchtenServiceLoader
. Es ist nichts Falsches daran, esSupplier
dann implementieren zu lassen . Aber wenn Sie es nicht brauchen, erstellen Sie es nicht. Wenn Sie nur eine benötigenSupplier<String>
, reicht es bereits aus, diese zu verwenden,DeclaringClass::generateTaskId
und die Notwendigkeit einer expliziten Klasse zu eliminieren, ist der Punkt dieser Sprachfunktion.TaskIdSupplier
Implementierung die Mühe wert war, aber dannServiceLoader
ging mir das Konzept völlig aus dem Kopf. Während dieser Diskussionen stießen wir auf einige Fragen wie: Was nütztSupplier
diepublic
Existenz, wenn man seine eigenen Schnittstellen entwickeln kann? und warum nichtpublic static Supplier<String> TASK_ID_SUPPLIER = () ->...
als globale Konstante? . (1/2)variable.genericMethodName(args)
stattmeaningfulMethodName(args)
. Die Verwendung eines Klassentyps zur Darstellung einer Funktion, sei es über einen Lambda-Ausdruck / eine Methodenreferenz oder eine manuell erstellte Klasse, ist nur ein Mittel , um die Funktion weiterzugeben (sofern in Java keine echten Funktionstypen vorhanden sind). Dies sollte nur bei Bedarf erfolgen.Wie andere gesagt haben, ist eine funktionale Schnittstelle eine Schnittstelle, die eine Methode verfügbar macht. Es kann mehr als eine Methode geben, aber alle anderen müssen eine Standardimplementierung haben. Der Grund, warum es als "funktionale Schnittstelle" bezeichnet wird, ist, dass es effektiv als Funktion fungiert. Da Sie Schnittstellen als Parameter übergeben können, sind Funktionen jetzt "erstklassige Bürger" wie in funktionalen Programmiersprachen. Dies hat viele Vorteile, und Sie werden sie ziemlich oft sehen, wenn Sie die Stream-API verwenden. Natürlich sind Lambda-Ausdrücke die offensichtlichste Hauptverwendung für sie.
quelle
Überhaupt nicht. Lambda-Ausdrücke sind der einzige Punkt dieser Anmerkung.
quelle
@Override
, die dem Compiler nur mitteilen möchte , dass Sie beabsichtigt haben, etwas zu schreiben, das "funktionsfähig" ist (und eine Fehlermeldung erhalten, wenn Sie ausrutschen).Ein Lambda-Ausdruck kann einem funktionalen Schnittstellentyp zugewiesen werden, ebenso wie Methodenreferenzen und anonyme Klassen.
Eine nette Sache über die spezifischen funktionalen Schnittstellen in
java.util.function
ist , dass sie zusammengesetzt werden , um neue Funktionen zu erstellen (wieFunction.andThen
undFunction.compose
,Predicate.and
usw.) aufgrund der praktisch Standard Methoden , die sie enthalten.quelle
Eine Schnittstelle mit nur einer abstrakten Methode wird als funktionale Schnittstelle bezeichnet. Die Verwendung von @FunctionalInterface ist nicht obligatorisch, es wird jedoch empfohlen, es mit funktionalen Schnittstellen zu verwenden, um zu vermeiden, dass versehentlich zusätzliche Methoden hinzugefügt werden. Wenn die Schnittstelle mit der Annotation @FunctionalInterface versehen ist und wir versuchen, mehr als eine abstrakte Methode zu verwenden, wird ein Compilerfehler ausgegeben.
quelle
Funktionsschnittstelle:
Beispiel 1:
Beispiel 2:
Beispiel 3:
Java8 Annotation -
@FunctionalInterface
Anwendungen der funktionalen Schnittstelle:
Um funktionale Schnittstellen zu lernen, lernen Sie die ersten Standardmethoden in der Schnittstelle. Nach dem Erlernen der funktionalen Schnittstelle ist es für Sie einfach, die Methodenreferenz und den Lambda-Ausdruck zu verstehen
quelle
Sie können Lambda in Java 8 verwenden
Weitere Informationen zu Java Lambdas und FunctionalInterfaces
quelle
@FunctionalInterface
ist eine neue Annotation, die mit Java 8 veröffentlicht wurde und Zieltypen für Lambda-Ausdrücke bereitstellt und zur Überprüfung der Kompilierungszeit Ihres Codes verwendet wird.Wenn Sie es verwenden möchten:
1- Ihre Schnittstelle darf nicht mehr als eine abstrakte Methode haben, da sonst ein Kompilierungsfehler auftritt.
1- Ihre Schnittstelle sollte rein sein, was bedeutet, dass die funktionale Schnittstelle von zustandslosen Klassen implementiert werden soll. Ein Beispiel für eine reine
Comparator
Schnittstelle ist , da sie nicht vom Status des Implementierers abhängt. In diesem Fall wird kein Kompilierungsfehler angegeben, aber in vielen Fällen von Ihnen wird nicht in der Lage sein, Lambda mit dieser Art von Schnittstellen zu verwendenDas
java.util.function
Paket enthält verschiedene Mehrzweck funktionelle Schnittstellen wiePredicate
,Consumer
,Function
, undSupplier
.Bitte beachten Sie auch, dass Sie Lambdas ohne diese Anmerkung verwenden können.
quelle
Neben anderen Antworten denke ich, dass der Hauptgrund dafür, "warum eine andere funktionale Schnittstelle als direkt mit Lambda-Ausdrücken verwendet wird", mit der Natur der objektorientierten Java-Sprache zusammenhängen kann.
Die Hauptattribute von Lambda-Ausdrücken sind: 1. Sie können um 2. herum übergeben werden und können in Zukunft zu einer bestimmten Zeit (mehrmals) ausgeführt werden. Um diese Funktion in Sprachen zu unterstützen, befassen sich einige andere Sprachen einfach mit dieser Angelegenheit.
Beispielsweise kann in Java Script eine Funktion (anonyme Funktion oder Funktionsliterale) als Objekt adressiert werden. Sie können sie also einfach erstellen und sie können auch einer Variablen zugewiesen werden und so weiter. Beispielsweise:
oder über ES6 können Sie eine Pfeilfunktion verwenden.
Bisher haben Java-Sprachdesigner nicht akzeptiert, die genannten Funktionen auf diese Weise zu handhaben (funktionale Programmiertechniken). Sie glauben, dass die Java-Sprache objektorientiert ist, und sollten dieses Problem daher mithilfe objektorientierter Techniken lösen. Sie möchten nicht auf die Einfachheit und Konsistenz der Java-Sprache verzichten.
Daher verwenden sie Schnittstellen. Wenn ein Objekt einer Schnittstelle mit nur einer Methode (ich meine funktionale Schnittstelle) benötigt wird, können Sie es durch einen Lambda-Ausdruck ersetzen. Sowie:
quelle