Kann mir jemand helfen, das zu verstehen? Ich hatte den Eindruck, dass wir Lamba-Ausdrücke nur in Java 8 verwenden können, wenn wir eine Schnittstelle implementieren und ihre Methoden überschreiben (indem wir anonyme Klassen durch Lambda-Ausdrücke ersetzen).
Auch in welcher Situation wird die Methode invoke(Runnable r)
aufgerufen?
In der folgenden Zeile
%Vor% Tatsächlich wird invoke(Callable)
aufgerufen. Der Grund ist:
() -> true
ist ein Lambda-Ausdruck, der formal null Parameter hat und ein Ergebnis zurückgibt. call()
von Callable
Schnittstelle. Beachten Sie, dass die Schnittstelle nicht die @FunctionalInterface
Annotation benötigt es muss nur eine einzige abstrakte Methode haben. Wenn Sie stattdessen invoke(Runnable)
aufrufen möchten, müssen Sie ein Lambda erstellen, das mit einer funktionalen Methode kompatibel ist, die null Parameter akzeptiert und kein Ergebnis zurückgibt (dh mit der Signatur von %Co_de% ). Etwas wie das:
Die Ausgabe von run()
erfolgt nur beim Ausführen.
Ein Lambda-Ausdruck liefert eine Implementierung für eine funktionale Schnittstelle. Dies ist, was Ihr Code-Snippet tut.
Ihr Aufruf an invoke
übergibt einen Lambda-Ausdruck ohne Argumente, der einen Wert zurückgibt (in Ihrem Fall ein boolean
). Daher entspricht es Object invoke(Callable c)
und nicht void invoke(Runnable r)
(da eine Methode Callable
call
einen Rückgabewert hat, während eine Methode Runnable
run
nichts zurückgibt).
ruft void invoke(Runnable r)
auf, da der Lambda-Ausdruck in diesem Fall keinen Rückgabetyp hat.
nur, wenn wir eine Schnittstelle implementieren und ihre Methoden überschreiben
Das ist mehr oder weniger das, was Sie hier tun. Nicht Methode s , sondern nur eine Methode: call()
. Dieser () -> true
-Teil ist Ihre Implementierung von Callable#call()
.
Mit anderen Worten, diese Zeile:
%Vor%wäre völlig äquivalent zu diesem:
%Vor% Lambda-Ausdruck ist eine weitere Möglichkeit, eine Instanz einer anonymen Klasse zu schreiben, um eine Instanz der anonymen Klasse einfacher zu schreiben. In JVM wird es nicht viel Speicher belegen, verglichen mit der normalen Java-Objekt-Erstellung mit new
(Ausführen von statischen Variablen, statischen Blöcken, Laden von Klassen aus der gesamten Hierarchie).
Lambda-Ausdruckssyntax:
%Vor% In Ihrem Testfall: String s = (String) invoke(() -> true);
Der Ausdruck hat den Rückgabetyp true
ohne Argument. Das Runnable
FunctionalInterface
stimmt also nicht mit dem Lambda-Ausdruck überein, weil es void run()
-Attribut hat. Er passt mit Callable
FuncationalInterface
mit Hilfe von V call()
.
Wie funktionieren Lambda-Ausdrücke unter der Haube?
Es mag so aussehen, als ob die Lambda-Ausdrücke nur die Syntax Zucker für anonyme innere Klassen sind, aber es gibt viel elegantere Ansätze. Die einfachste Erklärung ist: Der Lambda-Ausdruck wird durch eine neue Methode dargestellt und wird zur Laufzeit mit invokedynamic aufgerufen.
Quellcode:
%Vor%Bytecode entspricht:
%Vor%Innerhalb der JVM gibt es eine Lambda-Fabrik, die eine Instanz der funktionalen Schnittstelle (z. B. Runnable) aus der erzeugten Lambda-Methode (z. B. Lambda $ 1) erzeugt.
Lambda-Ausdrücke sind großartig, und es gibt noch mehr tolle Sachen in Java 8 ...