Ich lerne Lambda-Ausdrücke in Java 8. Kann mir jemand erklären, wie man Lambda-Ausdruck mit einer abstrakten Klasse verwendet, die nur eine Methode hat (wenn es möglich ist)?
Dies ist zum Beispiel die abstrakte Klasse:
%Vor% Und ich habe eine andere Klasse, die in ihrem Konstruktor eine Instanz von ClassA
:
Ich habe mich also gefragt, wie man so etwas schreibt:
%Vor%Offensichtlich funktioniert diese Aussage nicht, aber gibt es eine Möglichkeit, hier einen Lambda-Ausdruck zu verwenden oder nicht? Wenn ja, was mache ich falsch?
Nein, das kann nicht erreicht werden, weil ClassA
eine funktionale Schnittstelle sein muss. Eine funktionale Schnittstelle ist eine Schnittstelle, die genau eine abstrakte Methode enthält. Es kann zusätzlich zur abstrakten Methode keine oder mehrere Standardmethoden und / oder statische Methoden enthalten. Da eine funktionale Schnittstelle genau eine abstrakte Methode enthält, können Sie den Namen dieser Methode weglassen, wenn Sie sie mit einem Lambda-Ausdruck implementieren. Betrachten Sie beispielsweise die folgende Schnittstelle:
Der Zweck dieser Schnittstelle besteht darin, eine Methode bereitzustellen, die auf ein Objekt der Klasse T
wirkt und eine boolean
zurückgibt. Sie könnten eine Methode verwenden, die eine Instanz der Klasse übernimmt, die diese wie folgt definierte Schnittstelle implementiert:
wo Data
klasse könnte so einfach sein wie:
Nun können Sie die obige Methode wie folgt aufrufen:
%Vor%Beachten Sie, dass die Methode hier keinen Namen hat. Dies ist möglich, weil die Schnittstelle nur eine abstrakte Methode hat, so dass der Compiler den Namen herausfinden kann. Dies kann verkürzt werden zu:
%Vor% Beachten Sie, dass hier keine geschweiften Klammern und kein Rückgabe-Schlüsselwort stehen. Dies ist möglich, weil die Methode einen booleschen Wert zurückgibt und der Ausdruck d.value > 1
ebenfalls einen booleschen Wert zurückgibt. Der Compiler kann daher herausfinden, dass der Wert dieses Ausdrucks von der Methode zurückgegeben werden soll. Dies kann noch mehr verkürzt werden:
Beachten Sie, dass es keine Typdeklaration von d
gibt! Der Compiler kann alle benötigten Informationen herausfinden, da die Schnittstelle nur eine abstrakte Methode hat und diese Methode nur einen Parameter hat. Du musst also nicht all diese Dinge in deinem Code schreiben.
Vergleichen Sie den obigen Ansatz mit dem alten Java 7-Stil, indem Sie eine innere Klasse verwenden, die dasselbe bewirkt:
Sie können nur eine funktionale Schnittstelle mit einem Lambda-Ausdruck instanziieren.
Zum Beispiel:
Wenn Sie ClassA
als Schnittstelle ändern (Sie möchten sie wahrscheinlich umbenennen):
und behalten ClassB
, wie es ist:
Sie können eine Instanz von (die Schnittstelle) ClassA
an den ClassB
-Konstruktor übergeben mit:
Auf der anderen Seite, Ihr
%Vor%Versuch schlägt aus mehreren Gründen fehl:
ClassA
instanziieren könnten (wenn sie nicht abstrakt war), hat Ihre ClassA
keinen Konstruktor, der eine funktionale Schnittstelle als Argument akzeptiert, so dass Sie () -> System.out.println("Hello")
nicht als Argument übergeben können ClassA
's Konstruktor. Nun, Sie könnten Ihre Klassen ändern, um etwas in diese Richtung schreiben zu können:
%Vor% Aber dazu müssten Sie den Konstruktor von ClassA
ändern, um eine Implementierung einer funktionalen Schnittstelle wie java.lang.Runnable
:
Natürlich müssen Sie die abstrakte Methode in ClassA
implementieren, siehe das obige Beispiel.