Gibt es eine Möglichkeit, eine Rückruffunktion in einer Java-Methode zu übergeben?
Das Verhalten, das ich nachahmen möchte, ist ein .NET-Delegat, der an eine Funktion übergeben wird.
Ich habe Leute gesehen, die vorgeschlagen haben, ein separates Objekt zu erstellen, aber das scheint übertrieben, aber ich bin mir bewusst, dass manchmal Overkill der einzige Weg ist, Dinge zu tun.
java
callback
function-pointers
Omar Kooheji
quelle
quelle
Antworten:
Wenn Sie so etwas wie einen anonymen .NET-Delegaten meinen, kann auch die anonyme Klasse von Java verwendet werden.
quelle
Seit Java 8 gibt es Lambda und Methodenreferenzen:
Wenn Sie beispielsweise eine funktionale Schnittstelle wünschen,
A -> B
wie z.dann kann man es so nennen
Sie können auch die Klassenmethode übergeben. Angenommen, Sie haben:
Dann können Sie tun:
Hinweis :
Hier habe ich die Funktionsschnittstelle verwendet
Function<A,B>
, aber es gibt viele andere im Paketjava.util.function
. Die bemerkenswertesten sindSupplier
::void -> A
Consumer
::A -> void
BiConsumer
::(A,B) -> void
Function
::A -> B
BiFunction
::(A,B) -> C
und viele andere, die sich auf einige der Eingabe- / Ausgabetypen spezialisiert haben. Wenn es dann nicht das bietet, was Sie benötigen, können Sie Ihre eigene Funktionsschnittstelle wie folgt erstellen:
Anwendungsbeispiel:
quelle
java.util.function
ist, wonach Sie suchen, dann können Sie loslegen. Dann können Sie mit Generika für die E / A spielen. (?)java.util.function
nicht ausreichen.Der Einfachheit halber können Sie ein Runnable verwenden :
Verwendung:
quelle
public interface SimpleCallback { void callback(Object... objects); }
Dies ist recht einfach und kann nützlich sein, wenn Sie auch einige Parameter übergeben müssen.Ein bisschen Trottel:
Das Übergeben eines Rückrufs umfasst das Erstellen eines separaten Objekts in nahezu jeder OO-Sprache, sodass es kaum als Overkill angesehen werden kann. Was Sie wahrscheinlich meinen, ist, dass Sie in Java eine separate Klasse erstellen müssen, die ausführlicher (und ressourcenintensiver) ist als in Sprachen mit expliziten erstklassigen Funktionen oder Abschlüssen. Anonyme Klassen reduzieren jedoch zumindest die Ausführlichkeit und können inline verwendet werden.
quelle
Dennoch sehe ich, dass es den am meisten bevorzugten Weg gibt, nach dem ich gesucht habe. Er leitet sich im Wesentlichen aus diesen Antworten ab, aber ich musste ihn redundanter und effizienter manipulieren. Und ich denke, jeder sucht nach dem, was mir einfällt
Auf den Punkt ::
Machen Sie zuerst eine Schnittstelle so einfach
Jetzt können Sie diesen Rückruf ausführen, wann immer Sie möchten, um die Ergebnisse zu verarbeiten - wahrscheinlicher nach einem asynchronen Aufruf, und Sie möchten einige Dinge ausführen, die von diesen Wiederverwendungen abhängen
doSomething
ist die Funktion, die einige Zeit in Anspruch nimmt, wenn Sie einen Rückruf hinzufügen möchten, um Sie über die Ergebnisse zu informieren. Fügen Sie der Methode die Rückrufschnittstelle als Parameter hinzuhoffe mein Punkt ist klar, viel Spaß;)
quelle
Dies ist in Java 8 mit Lambdas sehr einfach.
quelle
Ich fand die Idee, die Reflect-Bibliothek zu implementieren, interessant und kam auf diese Idee, die meiner Meinung nach recht gut funktioniert. Der einzige Nachteil ist, dass Sie die Überprüfung der Kompilierungszeit verlieren, wenn Sie gültige Parameter übergeben.
Du benutzt es so
quelle
Eine Methode ist (noch) kein erstklassiges Objekt in Java; Sie können einen Funktionszeiger nicht als Rückruf übergeben. Erstellen Sie stattdessen ein Objekt (das normalerweise eine Schnittstelle implementiert), das die von Ihnen benötigte Methode enthält, und übergeben Sie diese.
Es wurden Vorschläge für Schließungen in Java gemacht, die das von Ihnen gesuchte Verhalten liefern würden. In der kommenden Java 7-Version werden jedoch keine Vorschläge enthalten sein.
quelle
Wenn ich diese Art von Funktionalität in Java benötige, verwende ich normalerweise das Observer-Muster . Es impliziert zwar ein zusätzliches Objekt, aber ich denke, es ist ein sauberer Weg und ein weithin verstandenes Muster, das die Lesbarkeit des Codes verbessert.
quelle
Überprüfen Sie die Abschlüsse, wie sie in der Lambdaj-Bibliothek implementiert wurden. Sie haben tatsächlich ein Verhalten, das C # -Delegierten sehr ähnlich ist:
http://code.google.com/p/lambdaj/wiki/Closures
quelle
Ich habe versucht, mit java.lang.reflect 'Rückruf' zu implementieren. Hier ein Beispiel:
quelle
timer.SetTimer ((int)(Math.random ()*10), System.out, "printf", "%s: [%s]", new Object[]{"null test", null});
. Ausgabe wird seinnull test: [null]
args[i].getClass()
? Mein Punkt ist, dass es nicht funktioniert, wenn Sie eine Methode basierend auf Argumenttypen auswählen. Es funktioniert mitString.format
, aber möglicherweise nicht mit etwas anderem, das akzeptiertnull
.argTypes
Array manuell übergeben kann , sodass wir jetztnull
Argumente / Parameter übergeben können, ohne dass eine NullPointerException aufgetreten ist. Beispielausgabe:NullParameterTest: String parameter=null, int parameter=888
Sie können dies auch
Callback
anhand desDelegate
Musters tun :Callback.java
PagerActivity.java
CustomPagerAdapter.java
quelle
Ich habe vor kurzem angefangen, so etwas zu tun:
quelle
es ist ein bisschen alt, aber trotzdem ... Ich fand die Antwort von Peter Wilkinson nett, bis auf die Tatsache, dass es für primitive Typen wie int / Integer nicht funktioniert. Das Problem ist das
.getClass()
für dieparameters[i]
, das zum Beispiel zurückgibtjava.lang.Integer
, was andererseits vongetMethod(methodName,parameters[])
(Javas Fehler) nicht richtig interpretiert wird ...Ich habe es mit dem Vorschlag von Daniel Spiewak kombiniert ( in seiner Antwort darauf ); Zu den Schritten zum Erfolg gehörten: Abfangen
NoSuchMethodException
->getMethods()
-> Suchen nach dem passenden durchmethod.getName()
-> und anschließendes explizites Durchlaufen der Liste der Parameter und Anwenden der Daniels-Lösung, z. B. Identifizieren der Typübereinstimmungen und der Signaturübereinstimmungen.quelle
Ich finde die Verwendung einer abstrakten Klasse eleganter:
quelle
object
den anderen "benachrichtigt",object
wenn etwas Wesentliches aufgetreten ist, sodass der zweiteobject
das Ereignis behandeln kann. Duabstract class
bist niemals ein Separaterobject
, es ist nur ein Separaterclass
. Sie verwenden nur eineobject
und werden unterschiedlichclasses
, um unterschiedliche Funktionen auszuführen. Dies ist die Essenz des Polymorphismus und nicht das Rückrufmuster.Grundsätzlich ist es nicht möglich, das Objekt einer Schnittstelle zu erstellen, da die Schnittstelle keine Objekte haben kann.
Die Option besteht darin, eine Klasse die Schnittstelle implementieren zu lassen und diese Funktion dann mit dem Objekt dieser Klasse aufzurufen. Aber dieser Ansatz ist wirklich ausführlich.
Alternativ können Sie eine neue HelloWorld () schreiben (* oberserve dies ist eine Schnittstelle, keine Klasse) und anschließend die Definition der Schnittstellenmethoden selbst vornehmen. (* Diese Definition ist in Wirklichkeit die anonyme Klasse). Dann erhalten Sie die Objektreferenz, über die Sie die Methode selbst aufrufen können.
quelle
Erstellen Sie eine Schnittstelle und erstellen Sie dieselbe Schnittstelleneigenschaft in der Rückrufklasse.
Implementieren Sie nun in der Klasse, in der Sie zurückgerufen werden möchten, die oben erstellte Schnittstelle. und übergeben Sie auch "dieses" Objekt / Referenz Ihrer Klasse, um zurückgerufen zu werden.
quelle