0
votes

Java runnable comme évaluation de l'argument

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:

  • Mise en œuvre runnable personnalisée xxx
    • ici où le runnable est passé comme argument: xxx
      • L'objet de réception Store Le ChallessRePortDélégation Instance sous achèvement de l'opération , attendez un délai d'attente puis exécutez ce code. xxx

        Le code ci-dessus soulève un nullpointException à l'exécution de la dernière partie du code, dans la méthode d'exécution.

        [EDIT]

        Le NullPointerException EXCEPTION est lancé car les deux getfromchaglallengereport () et gettochallengereport () (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é () (troisième partie du code)

        [EDIT2]

        J'ai reproduit la situation dans ce code simple : xxx

        Le comportement que je veux réaliser est l'impression de xxx

        mais c'est ce que je reçois xxx


11 commentaires

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 () sont uniquement appelées lorsque exécuté () est appelé, pas lorsque le exécutable est déclaré. Peut-être montrer plus de code complet (ce n'est pas clair là où le this.chalengesmanager.recordchalenge () est appelé, ni à quelle classe complète () 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 au lieu d'envelopper une autre? À quoi servait la deuxième tâche ?


@Slaw Dans ce contexte, la deuxième tâche est inutile bien sûr, mais dans mon application se produit des trucs où system.out.println ("moyen"); 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.


3 Réponses :


-1
votes

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.

En outre, essayez d'utiliser un appelable ou un fournisseur plutôt que vous êtes clairement intéressé à renvoyer certaines valeurs des sous-routines.


0 commentaires

0
votes

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();
}


0 commentaires

-1
votes

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);
        }
    }
}


0 commentaires