Ich lese über die neuen Funktionen unter: http://www.javaworld.com/article/2078836/java-se/love-and-hate-for-java-8.html
Ich habe das folgende Beispiel gesehen:
Verwenden der anonymen Klasse:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
System.out.println("Action Detected");
}
});
Mit Lambda:
button.addActionListener(e -> {
System.out.println("Action Detected");
});
Was würde jemand mit einem tun, MouseListener
wenn er mehrere Methoden innerhalb der anonymen Klasse implementieren möchte, z.
public void mousePressed(MouseEvent e) {
saySomething("Mouse pressed; # of clicks: "
+ e.getClickCount(), e);
}
public void mouseReleased(MouseEvent e) {
saySomething("Mouse released; # of clicks: "
+ e.getClickCount(), e);
}
... und so weiter?
java
lambda
java-8
anonymous-class
Menios
quelle
quelle
actionPerformed
der Schnittstelle implementierenActionListener
?!MousePressedListener
undMouseReleasedListener
und zwei MethodenaddMousePressedListener(Button, MousePressedListener)
und erstellenaddMouseReleasedListener(Button, MouseReleasedListener)
. Anschließend können Sie Lambdas verwenden, um diese Ereignishandler zu implementieren.Antworten:
Sie können Schnittstellen mit mehreren Methoden mit Lambdas verwenden, indem Sie Hilfsschnittstellen verwenden. Dies funktioniert mit solchen Listener-Schnittstellen, bei denen die Implementierung unerwünschter Methoden trivial ist (dh wir können nur das tun, was
MouseAdapter
auch angeboten wird):Sie müssen eine solche Hilfsschnittstelle nur einmal definieren.
Jetzt können Sie einen Listener für Klickereignisse
Component
c
wie folgt hinzufügen :quelle
mouseClicked
Methode, die als abstrakte Methode in derMouseListener
Schnittstelle deklariert und von derClickedListener
Schnittstelle nicht überschrieben wurde (daher der Name).Ab JLS 9.8
Lambdas benötigen diese Funktionsschnittstellen und sind daher auf ihre einzige Methode beschränkt. Anonyme Schnittstellen müssen weiterhin für die Implementierung von Schnittstellen mit mehreren Methoden verwendet werden.
quelle
Das Lambda EG hat dieses Problem berücksichtigt. Viele Bibliotheken verwenden funktionale Schnittstellen, obwohl sie Jahre vor der Einführung der funktionalen Schnittstelle entwickelt wurden. Es kommt jedoch manchmal vor, dass eine Klasse über mehrere abstrakte Methoden verfügt und Sie nur eine davon mit einem Lambda als Ziel festlegen möchten.
Das offiziell empfohlene Muster hier ist die Definition von Fabrikmethoden:
Diese können direkt von den APIs selbst durchgeführt werden (dies können statische Methoden innerhalb von sein
MouseListener
) oder externe Hilfsmethoden in einer anderen Bibliothek sein, falls die Betreuer diese Bequemlichkeit nicht anbieten. Da die Anzahl der Situationen, in denen dies erforderlich war, gering ist und die Problemumgehung so einfach ist, schien es nicht zwingend, die Sprache weiter zu erweitern, um diesen Eckfall zu retten.Ein ähnlicher Trick wurde angewendet für
ThreadLocal
; Siehe die neue statische Factory-MethodewithInitial(Supplier<S>)
.(Übrigens, wenn dieses Problem auftaucht, ist das Beispiel fast immer
MouseListener
, was ermutigend ist, da es darauf hindeutet, dass die Gruppe von Klassen, die lambda-freundlich sein möchten, aber nicht, eigentlich ziemlich klein sind.)quelle
WindowListener
, aber nur relativ wenige.Ein Java
ActionListener
muss nur eine einzige Methode implementieren (actionPerformed(ActionEvent e)
). Dies passt gut in die Java 8- Funktion, sodass Java 8 ein einfaches Lambda zur Implementierung eines bietetActionListener
.Das
MouseAdapter
erfordert mindestens zwei Methoden, passt also nicht alsfunction
.quelle
Ich habe Adapterklassen erstellt, mit denen ich Listener mit Lambda-Funktion (einzeilig) schreiben kann, auch wenn die ursprüngliche Listener-Oberfläche mehr als eine Methode enthält.
Beachten Sie den InsertOrRemoveUpdate-Adapter, der zwei Ereignisse zu einem zusammenfasst.
Meine ursprüngliche Klasse enthielt auch Implementierungen für WindowFocusListener, TableModelListener, TableColumnModelListener und TreeModelListener, aber dadurch wurde der Code über das SO-Limit von 30000 Zeichen verschoben.
quelle
Auf Standardmethoden kann nicht über Lambda-Ausdrücke zugegriffen werden. Der folgende Code wird nicht kompiliert:
Arbeiten Sie nur mit der funktionalen Schnittstelle (nur einzelne abstrakte Methode + beliebig viele Standardmethoden), sodass Lambda-Ausdruck nur mit abstrakter Methode funktioniert
quelle