Bitte verweisen Sie Personen nicht auf veraltete Informationen. Eine etwas längere Suche hätte Sie zu der aktuelleren Version geführt: cr.openjdk.java.net/~briangoetz/lambda/lambda-state-4.html , die selbst 18 Monate alt und in vielen Fällen veraltet ist setzt. Die Frage des OP wird unter lambdafaq.org/what-is-a-functional-interface beantwortet , einer Seite in einer FAQ, die ich in einer bis vor kurzem sich schnell ändernden Sprach- und API-Entwicklung auf dem neuesten Stand zu halten versuche.
Maurice Naftalin
1
@MauriceNaftalin Sie können auch einfach den Java-Trail verknüpfen , der vom Entwicklungsteam auf dem neuesten Stand gehalten wird.
Brian
1
Der aktuelle Begriff lautet "Funktionsschnittstelle".
Newacct
1
@ MauriceNaftalin: Entschuldigung, habe das verpasst. Hätte sicherlich damit zu tun gehabt, wenn ich das gefunden hätte.
Jon Skeet
Antworten:
141
Zusammengefasst den Link Jon geschrieben 1 , falls es jemals untergeht, „SAM“ steht für „Single abstrakte Methode“ und „SAM-Typ“ bezieht sich auf Schnittstellen wie Runnable, Callableusw. Lambda - Ausdrücke, ein neues Feature in Java 8 sind wird als SAM-Typ betrachtet und kann frei in diese konvertiert werden.
Zum Beispiel mit einer Schnittstelle wie dieser:
publicinterfaceCallable<T>{public T call();}
Sie können einen CallableLambda-Ausdruck wie folgt deklarieren :
Callable<String> strCallable =()->"Hello world!";System.out.println(strCallable.call());// prints "Hello world!"
Lambda-Ausdrücke sind in diesem Zusammenhang meist nur syntaktischer Zucker. Sie sehen im Code besser aus als anonyme Klassen und sind weniger restriktiv bei der Benennung von Methoden. Nehmen Sie dieses Beispiel aus dem Link:
Auf diese Weise wird eine Comparatorbestimmte Methode verwendet, die nicht denselben Namen hat wie Comparator.compare. Auf diese Weise müssen Sie nicht der Benennung der Schnittstellen von Methoden folgen, und Sie können mehrere Vergleichsüberschreibungen in einer Klasse vornehmen und dann die Komparatoren im laufenden Betrieb über erstellen die Lambda-Ausdrücke.
Tiefer gehen ...
Auf einer tieferen Ebene implementiert Java diese mithilfe der invokedynamicin Java 7 hinzugefügten Bytecode-Anweisung. Ich habe bereits gesagt, dass durch das Deklarieren eines Lambda eine Instanz einer anonymen Klasse Callableoder einer Comparableähnlichen Klasse erstellt wird, dies ist jedoch nicht unbedingt der Fall. Stattdessen wird beim ersten Aufruf von invokedynamicein Lambda-Funktionshandler mithilfe der LambdaMetafactory.metafactoryMethode erstellt und diese zwischengespeicherte Instanz in zukünftigen Aufrufen des Lambda verwendet. Weitere Informationen finden Sie in dieser Antwort .
Dieser Ansatz ist komplex und umfasst sogar Code, der primitive Werte und Referenzen direkt aus dem Stapelspeicher lesen kann, um ihn in Ihren Lambda-Code zu übertragen (z. B. um ein Object[]Array zum Aufrufen Ihres Lambda zuzuweisen ), ermöglicht jedoch zukünftige Iterationen der Lambda-Implementierung um alte Implementierungen zu ersetzen, ohne sich um die Bytecode-Kompatibilität sorgen zu müssen. Wenn die Ingenieure von Oracle die zugrunde liegende Lambda-Implementierung in einer neueren Version der JVM ändern, verwendet Lambdas, das auf einer älteren JVM kompiliert wurde, automatisch die neuere Implementierung, ohne dass der Entwickler Änderungen vornimmt.
1 Die Syntax des Links ist veraltet. Schauen Sie sich den Lambda Expressions Java Trail an, um die aktuelle Syntax zu sehen.
Sind Sie sicher #{ "Hello world!" };, dass die Syntax korrekt ist? Ich dachte, man würde es in einem Lambda-Ausdruck wie ausdrücken () -> "Hello world!".
Asgs
Ah ja. Ich habe gerade die Kommentare von @ Maurice gelesen. Sie sollten diesen Beitrag bearbeiten, um die neuesten Informationen wiederzugeben. Gut zu wissen, dass #{}Lambdas zuvor so vertreten waren.
Asgs
1
@asgs Ich hatte unten einen kleinen Klappentext, der auf den Java-Trail zeigte, aber ich habe die Antwort trotzdem aktualisiert, um die aktuelle Syntax zu verwenden.
Antworten:
Zusammengefasst den Link Jon geschrieben 1 , falls es jemals untergeht, „SAM“ steht für „Single abstrakte Methode“ und „SAM-Typ“ bezieht sich auf Schnittstellen wie
Runnable
,Callable
usw. Lambda - Ausdrücke, ein neues Feature in Java 8 sind wird als SAM-Typ betrachtet und kann frei in diese konvertiert werden.Zum Beispiel mit einer Schnittstelle wie dieser:
Sie können einen
Callable
Lambda-Ausdruck wie folgt deklarieren :Lambda-Ausdrücke sind in diesem Zusammenhang meist nur syntaktischer Zucker. Sie sehen im Code besser aus als anonyme Klassen und sind weniger restriktiv bei der Benennung von Methoden. Nehmen Sie dieses Beispiel aus dem Link:
Auf diese Weise wird eine
Comparator
bestimmte Methode verwendet, die nicht denselben Namen hat wieComparator.compare
. Auf diese Weise müssen Sie nicht der Benennung der Schnittstellen von Methoden folgen, und Sie können mehrere Vergleichsüberschreibungen in einer Klasse vornehmen und dann die Komparatoren im laufenden Betrieb über erstellen die Lambda-Ausdrücke.Tiefer gehen ...
Auf einer tieferen Ebene implementiert Java diese mithilfe der
invokedynamic
in Java 7 hinzugefügten Bytecode-Anweisung. Ich habe bereits gesagt, dass durch das Deklarieren eines Lambda eine Instanz einer anonymen KlasseCallable
oder einerComparable
ähnlichen Klasse erstellt wird, dies ist jedoch nicht unbedingt der Fall. Stattdessen wird beim ersten Aufruf voninvokedynamic
ein Lambda-Funktionshandler mithilfe derLambdaMetafactory.metafactory
Methode erstellt und diese zwischengespeicherte Instanz in zukünftigen Aufrufen des Lambda verwendet. Weitere Informationen finden Sie in dieser Antwort .Dieser Ansatz ist komplex und umfasst sogar Code, der primitive Werte und Referenzen direkt aus dem Stapelspeicher lesen kann, um ihn in Ihren Lambda-Code zu übertragen (z. B. um ein
Object[]
Array zum Aufrufen Ihres Lambda zuzuweisen ), ermöglicht jedoch zukünftige Iterationen der Lambda-Implementierung um alte Implementierungen zu ersetzen, ohne sich um die Bytecode-Kompatibilität sorgen zu müssen. Wenn die Ingenieure von Oracle die zugrunde liegende Lambda-Implementierung in einer neueren Version der JVM ändern, verwendet Lambdas, das auf einer älteren JVM kompiliert wurde, automatisch die neuere Implementierung, ohne dass der Entwickler Änderungen vornimmt.1 Die Syntax des Links ist veraltet. Schauen Sie sich den Lambda Expressions Java Trail an, um die aktuelle Syntax zu sehen.
quelle
#{ "Hello world!" };
, dass die Syntax korrekt ist? Ich dachte, man würde es in einem Lambda-Ausdruck wie ausdrücken() -> "Hello world!"
.#{}
Lambdas zuvor so vertreten waren.