Je développe un serveur client dans Java et j'ai rencontré problème à adopter une implémentation couléelle personnalisée comme argument d'un objet à un autre. Le problème est que le code runnable est évalué (non exécuté) à la définition, mais je veux que cela soit évalué à l'invocation. Y a-t-il un moyen d'atteindre ce comportement?
Ici, le code affecté par ce problème: p>
ChallessRePortDélégation CODE> Instance sous achèvement de l'opération code>, attendez un délai d'attente puis exécutez ce code. LI>
ul> xxx pré> Le code ci-dessus soulève un nullpointException code> à l'exécution de la dernière partie du code, dans la méthode d'exécution. P> [EDIT] P>
Le NullPointerException code> EXCEPTION est lancé car les deux getfromchaglallengereport () code> et gettochallengereport () code> (deuxième partie du code ) Renvoie initialement NULL (lorsque l'exécution est définie et passée comme argument),
mais ils retourneraient des valeurs cohérentes au temps d'invocation exécuté () code> (troisième partie du code) p> [EDIT2] p>
J'ai reproduit la situation dans ce code simple : p> xxx pré> Le comportement que je veux réaliser est l'impression de p> xxx pré> mais c'est ce que je reçois p> xxx pré> p>
3 Réponses :
Si vous voulez évaluer immédiatement quelque chose. Je suggérerais d'utiliser un alonchable du tout. Il ressemble à un modèle APTI, essayant de passer du code autour de tout ce que vous voulez est la valeur / l'invocation. P>
En outre, essayez d'utiliser un appelable ou un fournisseur plutôt que vous êtes clairement intéressé à renvoyer certaines valeurs des sous-routines. p>
Un exemple très simple. Permet de créer un champ d'affichage avec un champ.
public static void main (String[] args) { var x = new Runnable(){ int a = 0; int getA(){ return a; } void setA(int v){ a = v; } public void run(){ System.out.println("A : " + getA()); } }; x.run(); x.setA(5); x.run(); }
J'ai trouvé une solution de travail pour ce problème, peut-être trivial pour ceux qui venaient de la programmation fonctionnelle.
en conséquence à l'exemple dans la dernière modification ([EDIT2]) P>
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; public class TestEvaluation { public static void main(String[] args) throws InterruptedException { Middle middle = new Middle(); middle.register(new Consumer<Values>() { @Override public void accept(Values values) { System.out.println("a is: " + values.getA()); System.out.println("b is: " + values.getB()); } }); Thread.sleep(2000); } static class Values { private int a = 0; private int b = 0; public int getA() { return a; } public void setA(int a) { this.a = a; } public int getB() { return b; } public void setB(int b) { this.b = b; } } static class Middle { private ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(1); public void register(Consumer<Values> passed) { Consumer<Values> middleConsumer = new Consumer<Values>() { @Override public void accept(Values values) { System.out.println("Middle"); passed.accept(values); } }; Leaf leaf = new Leaf(middleConsumer); pool.schedule(leaf, 1, TimeUnit.SECONDS); } } static class Leaf implements Runnable { public Consumer<Values> task; public Leaf(Consumer<Values> task) { this.task = task; } @Override public void run() { Values values = new Values(); values.setA(5); values.setB(5); System.out.println("Leaf"); task.accept(values); } } }
Votre question est d'où vient la NPE? Il n'y a aucun moyen de dire à ces informations.
J'ai essayé de mieux expliquer. Voir la dernière modification. Merci
Pas sûr de ce que vous voulez dire. Les méthodes
getxxxchallengère () code> sont uniquement appelées lorsque
exécuté () code> est appelé, pas lorsque le
exécutable code> est déclaré. Peut-être montrer plus de code complet (ce n'est pas clair là où le
this.chalengesmanager.recordchalenge () code> est appelé, ni à quelle classe
complète () code> appartient). Avez-vous passé cela avec des points d'arrêt?
Veuillez fournir un exemple de reproductible minimal démontrer le problème et inclure la trace complète de la ou des erreurs.
@Slaw j'ai fourni un exemple simplifié pour reproduire le problème ([EDIT2])
Vous avez une tâche enveloppée dans une tâche. Vous définissez A et B de la tâche wastter, mais la tâche originale A et B ne changent pas. Essayez-vous de rendre cela compliqué exprès?
@matt tu as raison. J'ai compris votre réponse et donc la cause du problème mais de toute façon je ne peux pas comprendre comment atteindre le comportement que je veux. Sais-tu comment faire cela?
Appelez SETA et SETB sur l'objet que vous souhaitez modifier A et B de.
Pourquoi non seulement utiliser une instance de
tâche code> au lieu d'envelopper une autre? À quoi servait la deuxième tâche
code>?
@Slaw Dans ce contexte, la deuxième tâche
code> est inutile bien sûr, mais dans mon application se produit des trucs où
system.out.println ("moyen"); code> est placé
Vous pouvez remplacer les getters / setters de la tâche wrapper pour déléguer à la tâche enveloppée. Ou vous pouvez appeler les configurateurs de la tâche emballée lorsque les Setteurs de la tâche Wrapper sont invoqués.