Existe-t-il un moyen de passer une fonction de rappel dans une méthode Java?
Le comportement que j'essaie d'imiter est un délégué .Net passé à une fonction.
J'ai vu des gens suggérer de créer un objet séparé, mais cela semble exagéré, mais je suis conscient que parfois exagérer est la seule façon de faire les choses.
java
callback
function-pointers
Omar Kooheji
la source
la source
Réponses:
Si vous voulez dire quelque chose comme le délégué anonyme .NET, je pense que la classe anonyme de Java peut également être utilisée.
la source
Depuis Java 8, il existe des références lambda et méthodes:
Par exemple, si vous souhaitez une interface fonctionnelle
A -> B
telle que:alors tu peux l'appeler comme ça
Vous pouvez également passer la méthode de classe. Dites que vous avez:
Ensuite, vous pouvez faire:
Remarque :
Ici, j'ai utilisé l'interface fonctionnelle
Function<A,B>
, mais il y en a beaucoup d'autres dans le packagejava.util.function
. Les plus notables sontSupplier
:void -> A
Consumer
:A -> void
BiConsumer
:(A,B) -> void
Function
:A -> B
BiFunction
:(A,B) -> C
et beaucoup d'autres qui se spécialisent sur certains des types d'entrée / sortie. Ensuite, s'il ne fournit pas celui dont vous avez besoin, vous pouvez créer votre propre interface fonctionnelle comme ceci:
Exemple d'utilisation:
la source
java.util.function
est ce que vous recherchez, alors vous êtes prêt à partir. Ensuite, vous pouvez jouer avec des génériques pour les E / S. (?)java.util.function
ne sont pas suffisantes.Pour plus de simplicité, vous pouvez utiliser un Runnable :
Usage:
la source
public interface SimpleCallback { void callback(Object... objects); }
Ceci est assez simple et pourrait être utile, vous devez également passer certains paramètres.Un peu de pinaillerie:
Passer un rappel inclut la création d'un objet séparé dans à peu près n'importe quel langage OO, donc cela peut difficilement être considéré comme excessif. Ce que vous voulez probablement dire, c'est qu'en Java, cela vous oblige à créer une classe distincte, qui est plus verbeuse (et plus gourmande en ressources) que dans les langages avec des fonctions ou des fermetures explicites de première classe. Cependant, les classes anonymes réduisent au moins la verbosité et peuvent être utilisées en ligne.
la source
pourtant je vois qu'il y a la manière la plus préférée qui était ce que je cherchais .. il est fondamentalement dérivé de ces réponses mais j'ai dû le manipuler de manière plus redondante et efficace .. et je pense que tout le monde cherche ce que je propose
Jusqu'au point::
faites d'abord une interface aussi simple
maintenant pour exécuter ce rappel quand vous le souhaitez pour gérer les résultats - plus probablement après un appel asynchrone et vous voulez exécuter des choses qui dépendent de ces réutilisations
doSomething
est la fonction qui prend un certain temps vous voulez y ajouter un rappel pour vous avertir lorsque les résultats sont arrivés, ajoutez l'interface de rappel en tant que paramètre de cette méthodeJ'espère que mon point est clair, profitez-en;)
la source
C'est très facile en Java 8 avec des lambdas.
la source
J'ai trouvé l'idée d'implémenter en utilisant la bibliothèque Reflect intéressante et j'ai proposé cela qui, je pense, fonctionne assez bien. Le seul inconvénient est de perdre la vérification à la compilation que vous passez des paramètres valides.
Vous l'utilisez comme ça
la source
Une méthode n'est pas (encore) un objet de première classe en Java; vous ne pouvez pas passer un pointeur de fonction comme rappel. Au lieu de cela, créez un objet (qui implémente généralement une interface) contenant la méthode dont vous avez besoin et transmettez-la.
Des propositions de fermetures en Java - qui fourniraient le comportement que vous recherchez - ont été faites, mais aucune ne sera incluse dans la prochaine version de Java 7.
la source
Lorsque j'ai besoin de ce type de fonctionnalité en Java, j'utilise généralement le modèle Observer . Cela implique un objet supplémentaire, mais je pense que c'est une manière propre de procéder, et c'est un modèle largement compris, ce qui contribue à la lisibilité du code.
la source
Vérifiez les fermetures comment elles ont été implémentées dans la bibliothèque lambdaj. Ils ont en fait un comportement très similaire aux délégués C #:
http://code.google.com/p/lambdaj/wiki/Closures
la source
J'ai essayé d'utiliser java.lang.reflect pour implémenter 'callback', voici un exemple:
la source
timer.SetTimer ((int)(Math.random ()*10), System.out, "printf", "%s: [%s]", new Object[]{"null test", null});
. la sortie seranull test: [null]
args[i].getClass()
? Mon point est que cela ne fonctionne pas si vous sélectionnez une méthode basée sur des types d'arguments. Cela fonctionne avecString.format
, mais peut ne pas fonctionner avec quelque chose d'autre qui acceptenull
.argTypes
tableau, donc maintenant nous pouvons passer unnull
argument / paramètre sans que NullPointerException ne se soit produit. Exemple de sortie:NullParameterTest: String parameter=null, int parameter=888
Vous pouvez également faire le en
Callback
utilisant leDelegate
modèle:Callback.java
PagerActivity.java
CustomPagerAdapter.java
la source
J'ai récemment commencé à faire quelque chose comme ça:
la source
c'est un peu vieux, mais quand même ... J'ai trouvé la réponse de Peter Wilkinson sympa à part le fait qu'elle ne fonctionne pas pour les types primitifs comme int / Integer. Le problème est le
.getClass()
pour leparameters[i]
, qui retourne par exemplejava.lang.Integer
, qui par contre ne sera pas correctement interprété pargetMethod(methodName,parameters[])
(faute de Java) ...Je l'ai combiné avec la suggestion de Daniel Spiewak ( dans sa réponse à cela ); les étapes du succès comprenaient: attraper
NoSuchMethodException
->getMethods()
-> rechercher celui correspondant parmethod.getName()
-> puis parcourir explicitement la liste des paramètres et appliquer la solution Daniels, en identifiant les correspondances de type et les correspondances de signature.la source
Je pense que l'utilisation d'une classe abstraite est plus élégante, comme ceci:
la source
object
"avertisse" un autreobject
lorsque quelque chose d'important s'est produit, afin que le secondobject
puisse gérer l'événement. Votreabstract class
n'est jamais un séparéobject
, ce n'est qu'un séparéclass
. Vous n'en utilisez qu'unobject
et vous devenez différentclasses
pour exécuter différentes fonctions, ce qui est l'essence même du polymorphisme, pas le modèle de rappel.Fondamentalement, si vous voulez créer l'objet d'une interface, ce n'est pas possible, car l'interface ne peut pas avoir d'objets.
L'option est de laisser une classe implémenter l'interface, puis d'appeler cette fonction en utilisant l'objet de cette classe. Mais cette approche est vraiment verbeuse.
Alternativement, écrivez new HelloWorld () (* oberserve c'est une interface pas une classe) puis suivez-le avec la définition des méthodes d'interface elle-même. (* Cette définition est en réalité la classe anonyme). Ensuite, vous obtenez la référence d'objet à travers laquelle vous pouvez appeler la méthode elle-même.
la source
Créez une interface et créez la même propriété d'interface dans la classe de rappel.
Maintenant, dans la classe où vous souhaitez être rappelé, implémentez l'interface créée ci-dessus. et Passez également "cet" objet / référence de votre classe à rappeler.
la source