Angenommen, ich habe die folgende Funktionsschnittstelle in Java 8:
interface Action<T, U> {
U execute(T t);
}
Und für einige Fälle benötige ich eine Aktion ohne Argumente oder Rückgabetyp. Also schreibe ich so etwas:
Action<Void, Void> a = () -> { System.out.println("Do nothing!"); };
Es gibt mir jedoch Kompilierungsfehler, ich muss es schreiben als
Action<Void, Void> a = (Void v) -> { System.out.println("Do nothing!"); return null;};
Welches ist hässlich. Gibt es eine Möglichkeit, den Void
Typparameter loszuwerden ?
Runnable
, wonach Sie suchenRunnable r = () -> System.out.println("Do nothing!");
Antworten:
Die Syntax, nach der Sie suchen, ist mit einer kleinen Hilfsfunktion möglich, die a
Runnable
in konvertiertAction<Void, Void>
(Sie können sieAction
beispielsweise einfügen):quelle
@FunctionalInterface
. Er sagt nur, dass es nicht möglich ist, es zu verlängern ...Runnable
Aktion sollte ein benutzerdefinierter@FunctionalInterface
Vorgang ausgeführt werden.SideEffect
2. Die Notwendigkeit einer solchen Hilfsfunktion zeigt, dass etwas Seltsames vor sich geht und wahrscheinlich die Abstraktion unterbrochen ist.Verwenden
Supplier
Sie diese Option, wenn nichts benötigt wird, aber etwas zurückgegeben wird.Verwenden
Consumer
Sie diese Option, wenn etwas benötigt wird, aber nichts zurückgegeben wird.Verwenden
Callable
Sie diese Option, wenn ein Ergebnis zurückgegeben wird und möglicherweise ausgelöst wird (Thunk
im Allgemeinen ähnlich wie bei CS).Verwenden Sie,
Runnable
wenn es beides nicht tut und nicht werfen kann.quelle
public static void wrapCall(Runnable r) { r.run(); }
. Vielen DankDas Lambda:
stellt tatsächlich eine Implementierung für eine Schnittstelle dar, wie:
Das ist völlig anders als die, die Sie definiert haben. Deshalb erhalten Sie eine Fehlermeldung.
Da Sie Ihre nicht erweitern
@FunctionalInterface
oder eine brandneue vorstellen können, haben Sie meiner Meinung nach nicht viele Optionen. Sie können dieOptional<T>
Schnittstellen verwenden, um anzuzeigen, dass einige der Werte (Rückgabetyp oder Methodenparameter) fehlen. Dies wird den Lambda-Körper jedoch nicht einfacher machen.quelle
Something
Funktion kein Subtyp meinesAction
Typs sein kann und ich keine zwei verschiedenen Typen haben kann.Sie können eine Unterschnittstelle für diesen speziellen Fall erstellen:
Es verwendet eine Standardmethode , um die geerbte parametrisierte Methode zu überschreiben
Void execute(Void)
und den Aufruf an die einfachere Methode zu delegierenvoid execute()
.Das Ergebnis ist, dass es viel einfacher zu bedienen ist:
quelle
Das ist nicht möglich. Eine Funktion mit einem nicht ungültigen Rückgabetyp (auch wenn dies der Fall ist
Void
) muss einen Wert zurückgeben. Sie können jedoch statische Methoden hinzufügenAction
, mit denen Sie Folgendes erstellen könnenAction
:Damit können Sie Folgendes schreiben:
quelle
Ich denke, diese Tabelle ist kurz und nützlich:
Wie in den anderen Antworten erwähnt, ist die geeignete Option für dieses Problem a
Runnable
quelle
Fügen Sie eine statische Methode in Ihre Funktionsschnittstelle ein
Ausgabe
quelle
Ich denke nicht, dass dies möglich ist, da die Funktionsdefinitionen in Ihrem Beispiel nicht übereinstimmen.
Ihr Lambda-Ausdruck wird genau wie ausgewertet
während Ihre Erklärung aussieht wie
Als Beispiel, wenn Sie folgende Schnittstelle haben
Die einzige Art von Funktion (während der Instanziierung), die kompatibel ist, sieht aus
Wenn Sie keine return-Anweisung oder kein Argument haben, erhalten Sie einen Compilerfehler.
Wenn Sie also eine Funktion deklarieren, die ein Argument akzeptiert und eines zurückgibt, ist es meines Erachtens unmöglich, sie in eine Funktion umzuwandeln, die keine der oben genannten Funktionen ausführt.
quelle
Nur als Referenz, welche Funktionsschnittstelle als Methodenreferenz verwendet werden kann, wenn die Methode einen Wert auslöst und / oder zurückgibt.
quelle