Ich suche nach einer Möglichkeit, eine Methode als Referenz zu übergeben. Ich verstehe, dass Java keine Methoden als Parameter übergibt, möchte jedoch eine Alternative erhalten.
Mir wurde gesagt, dass Schnittstellen die Alternative zur Übergabe von Methoden als Parameter sind, aber ich verstehe nicht, wie eine Schnittstelle als Referenzmethode fungieren kann. Wenn ich das richtig verstehe, ist eine Schnittstelle einfach ein abstrakter Satz von Methoden, die nicht definiert sind. Ich möchte keine Schnittstelle senden, die jedes Mal definiert werden muss, da mehrere verschiedene Methoden dieselbe Methode mit denselben Parametern aufrufen können.
Was ich erreichen möchte, ist etwas Ähnliches:
public void setAllComponents(Component[] myComponentArray, Method myMethod) {
for (Component leaf : myComponentArray) {
if (leaf instanceof Container) { //recursive call if Container
Container node = (Container) leaf;
setAllComponents(node.getComponents(), myMethod);
} //end if node
myMethod(leaf);
} //end looping through components
}
aufgerufen wie:
setAllComponents(this.getComponents(), changeColor());
setAllComponents(this.getComponents(), changeSize());
Antworten:
Bearbeiten : Ab Java 8 sind Lambda-Ausdrücke eine gute Lösung, wie andere Antworten gezeigt haben. Die folgende Antwort wurde für Java 7 und früher geschrieben ...
Schauen Sie sich das Befehlsmuster an .
Bearbeiten: Wie Pete Kirkham betont , gibt es eine andere Möglichkeit, dies mit einem Besucher zu tun . Der Besucheransatz ist etwas
acceptVisitor()
komplizierter - Ihre Knoten müssen alle mit einer Methode besucherbewusst sein -, aber wenn Sie einen komplexeren Objektgraphen durchlaufen müssen, lohnt es sich, ihn zu untersuchen.quelle
In Java 8 können Sie eine Methode jetzt einfacher mit Lambda-Ausdrücken und Methodenreferenzen übergeben. Zunächst einige Hintergrundinformationen: Eine funktionale Schnittstelle ist eine Schnittstelle, die nur eine abstrakte Methode enthält, obwohl sie eine beliebige Anzahl von Standardmethoden (neu in Java 8) und statischen Methoden enthalten kann. Ein Lambda-Ausdruck kann die abstrakte Methode schnell implementieren, ohne dass die unnötige Syntax erforderlich ist, wenn Sie keinen Lambda-Ausdruck verwenden.
Ohne Lambda-Ausdrücke:
Mit Lambda-Ausdrücken:
Hier ist ein Auszug aus dem Java-Tutorial zu Lambda Expressions :
So können Sie eine Methode mit einem Lambda-Ausdruck "übergeben":
Die Klasse
C
kann durch die Verwendung von Methodenreferenzen wie folgt noch ein wenig verkürzt werden:quelle
::
Operator), spielt es keine Rolle, was A ist.a.changeThing(component)
kann in eine beliebige Anweisung oder einen beliebigen Codeblock geändert werden, solange void zurückgegeben wird.Verwenden Sie das
java.lang.reflect.Method
Objekt und rufen Sie aufinvoke
quelle
Seit Java 8 gibt es eine
Function<T, R>
Schnittstelle ( docs ) mit MethodeSie können damit Funktionen als Parameter an andere Funktionen übergeben. T ist der Eingabetyp der Funktion, R ist der Rückgabetyp.
In Ihrem Beispiel müssen Sie eine Funktion übergeben, die den
Component
Typ als Eingabe verwendet und nichts zurückgibtVoid
. In diesem FallFunction<T, R>
ist dies nicht die beste Wahl, da es keine Autoboxing vom Typ Void gibt. Die gesuchte Schnittstelle heißtConsumer<T>
( docs ) with methodEs würde so aussehen:
Und Sie würden es mit Methodenreferenzen aufrufen:
Angenommen, Sie haben die Methoden changeColor () und changeSize () in derselben Klasse definiert.
Wenn Ihre Methode mehr als einen Parameter akzeptiert, können Sie
BiFunction<T, U, R>
- T und U als Typen von Eingabeparametern und R als Rückgabetyp verwenden. Es gibt auchBiConsumer<T, U>
(zwei Argumente, kein Rückgabetyp). Leider müssen Sie für 3 und mehr Eingabeparameter selbst eine Schnittstelle erstellen. Zum Beispiel:quelle
Definieren Sie zunächst eine Schnittstelle mit der Methode, die Sie als Parameter übergeben möchten
Implementieren Sie eine Klasse mit der Methode
// So aufrufen
Auf diese Weise können Sie cmd als Parameter übergeben und den in der Schnittstelle definierten Methodenaufruf aufrufen
quelle
Dies gilt zwar noch nicht für Java 7 und darunter, aber ich glaube, wir sollten in die Zukunft schauen und zumindest die Änderungen erkennen , die in neuen Versionen wie Java 8 zu erwarten sind.
Diese neue Version bringt nämlich Lambdas und Methodenverweise auf Java (zusammen mit neuen APIs , die eine weitere gültige Lösung für dieses Problem darstellen. Obwohl sie noch eine Schnittstelle erfordern, werden keine neuen Objekte erstellt, und zusätzliche Klassendateien müssen Ausgabeverzeichnisse aufgrund unterschiedlicher nicht verschmutzen Handhabung durch die JVM.
Beide Geschmacksrichtungen (Lambda und Methodenreferenz) erfordern eine Schnittstelle, die mit einer einzigen Methode verfügbar ist, deren Signatur verwendet wird:
Namen von Methoden spielen von nun an keine Rolle mehr. Wenn ein Lambda akzeptiert wird, ist auch eine Methodenreferenz vorhanden. Um beispielsweise unsere Unterschrift hier zu verwenden:
Dies ist nur ein einfacher Schnittstellenaufruf, bis das Lambda 1 übergeben wird:
Dies wird Folgendes ausgeben:
Methodenreferenzen sind ähnlich. Gegeben:
und Haupt:
die Ausgabe wäre
real static method
. Methodenreferenzen können statisch, instanziell, nicht statisch mit beliebigen Instanzen und sogar Konstruktoren sein . Für den Konstruktor würde etwas ÄhnlichesClassName::new
verwendet.1 Dies wird von einigen nicht als Lambda angesehen, da es Nebenwirkungen hat. Es zeigt jedoch die Verwendung von einem auf eine einfachere Art und Weise zu visualisieren.
quelle
Als ich das letzte Mal nachgesehen habe, ist Java nicht in der Lage, von Haus aus das zu tun, was Sie wollen. Sie müssen "Workarounds" verwenden, um solche Einschränkungen zu umgehen. Aus meiner Sicht sind Schnittstellen eine Alternative, aber keine gute Alternative. Vielleicht hat dir jemand gesagt, dass das so etwas bedeutet:
Womit Sie sich dann aufrufen würden:
quelle
Wenn Sie diese Methoden nicht benötigen, um etwas zurückzugeben, können Sie sie dazu bringen, ausführbare Objekte zurückzugeben.
Dann benutze es wie folgt:
quelle
Ich habe kein explizites Beispiel für die Verwendung
java.util.function.Function
einer einfachen Methode als Parameterfunktion gefunden. Hier ist ein einfaches Beispiel:Grundsätzlich haben Sie ein
Foo
Objekt mit einem Standardkonstruktor. Amethod
, das als Parameter von demparametrisedMethod
Typ aufgerufen wirdFunction<String, Foo>
.Function<String, Foo>
bedeutet, dass die Funktion aString
als Parameter nimmt und a zurückgibtFoo
.Foo::Method
entspricht einem Lambda wiex -> Foo.method(x);
parametrisedMethod(Foo::method)
könnte als gesehen werdenx -> parametrisedMethod(Foo.method(x))
.apply("from a method")
ist grundsätzlich zu tunparametrisedMethod(Foo.method("from a method"))
Welches wird dann in der Ausgabe zurückkehren:
Das Beispiel sollte so laufen, wie es ist. Sie können dann kompliziertere Dinge aus den obigen Antworten mit verschiedenen Klassen und Schnittstellen ausprobieren.
quelle
Java hat einen Mechanismus, um Namen zu übergeben und aufzurufen. Es ist Teil des Reflexionsmechanismus. Ihre Funktion sollte zusätzliche Parameter der Klasse Method verwenden.
quelle
Ich bin kein Java-Experte, aber ich löse Ihr Problem folgendermaßen:
Ich definiere den Parameter in meiner speziellen Schnittstelle
Schließlich implementiere ich die getSearchText- Methode, während ich die initialize- Methode aufrufe .
quelle
Verwenden Sie das Observer-Muster (manchmal auch als Listener-Muster bezeichnet):
new ComponentDelegate()...
deklariert einen anonymen Typ, der die Schnittstelle implementiert.quelle
Hier ist ein grundlegendes Beispiel:
Ausgabe:
quelle
Ich habe hier keine Lösung gefunden, die zeigt, wie eine Methode mit daran gebundenen Parametern als Parameter einer Methode übergeben wird. Unten sehen Sie ein Beispiel dafür, wie Sie eine Methode mit bereits daran gebundenen Parameterwerten übergeben können.
Ein weiteres Beispiel zeigt, wie eine Methode übergeben wird, die tatsächlich etwas zurückgibt
quelle
Beispiel für eine Lösung mit Reflexion, übergebene Methode muss öffentlich sein
quelle
Ich schätze die obigen Antworten, konnte aber mit der folgenden Methode das gleiche Verhalten erzielen. eine Idee, die aus Javascript-Rückrufen entlehnt wurde. Ich bin offen für Korrekturen, obwohl bisher so gut (in Produktion).
Die Idee ist, den Rückgabetyp der Funktion in der Signatur zu verwenden, was bedeutet, dass die Ausbeute statisch sein muss.
Unten finden Sie eine Funktion, die einen Prozess mit einer Zeitüberschreitung ausführt.
quelle