web-dev-qa-db-fra.com

La variable locale finale ne peut pas être affectée, car elle est définie dans un type englobant

ratingS = new JSlider(1, 5, 3); 
ratingS.setMajorTickSpacing(1);
ratingS.setPaintLabels(true);
int vote;

class SliderMoved implements ChangeListener {
    public void stateChanged(ChangeEvent e) {
        vote = ratingS.getValue();
    }
}

ratingS.addChangeListener(new SliderMoved());

Si j'écris le code ci-dessus, Eclipse me dit ceci:

Impossible de faire référence à un vote variable non final dans une classe interne défini dans une méthode différente

Mais si j'ajoute final avant int vote, cela me donne cette erreur:

Le vote de la variable locale finale ne peut pas être attribué car il est défini dans un type englobant

Alors, comment résoudre?

16
smartmouse

Eh bien, l'astuce standard consiste à utiliser un tableau int de longueur un. Faites la var finale et écrivez dans var[0]. Il est très important de vous assurer de ne pas créer de course de données. En utilisant votre code comme exemple:

final int[] vote = {0};

class SliderMoved implements ChangeListener {
  public void stateChanged(ChangeEvent e) {
    vote[0] = ratingS.getValue();
  }
}

Étant donné que tout cela se produira sur l'EDT, y compris l'invocation de rappel, vous devriez être en sécurité. Vous devriez également envisager d'utiliser la classe anonyme:

ratingS.addChangeListener(new ChangeListener() {
  public void stateChanged(ChangeEvent e) { vote[0] = ratingS.getValue(); }
});
27
Marko Topolnik

Déplacer vote vers SliderMoved:

class SliderMoved implements ChangeListener {
    private int vote;
    public void stateChanged(ChangeEvent e) {
        this.vote = ratingS.getValue();
        // do something with the vote, you can even access
        // methods and fields of the outer class
    }
    public int getVote() {
        return this.vote;
    }
}

SliderMoved sm = new SliderMoved();
ratingS.addChangeListener(sm);

// if you need access to the actual rating...
int value = rattingS.getValue();

// ...or
int value2 = sm.getVote();

MODIFIER

Ou bien, passez une classe de modèle à l'écouteur de modification

public class Person {
    private String name;
    private int vote;
    public int getVote() {
        return this.vote;
    }
    public void setVote(int vote) {
        this.vote = vote;
    }
    // omitting other setter and getter
}

Person est utilisé comme suit:

 class SliderMoved implements ChangeListener {
    private Person person;
    public SliderMoved(Person person) {
        this.person = person;
    }
    public void stateChanged(ChangeEvent e) {
        this.person.setVote(ratingS.getValue());
    }
    public Person getPerson() {
        return this.person;
    }
}

Person person = new Person();

ratingS.addChangeListener(new SliderMoved(person));

// access the vote
int vote = person.getVote();
5
Peter Keller

Définir le niveau de conformité du compilateur sur 1.8 m'a permis de résoudre un problème similaire. Je ne comprends pas la raison mais vous pouvez essayer ceci.

Comment ça marche:

Faites un clic droit sur le projet -> Propriétés -> Compilateur Java. Et dans la fenêtre des propriétés du compilateur Java, définissez le niveau de conformité du compilateur sur 1.8.

2
Nadeem

J'ai finalement résolu de déclarer le vote comme variable d'instance (privé) dans la classe principale.

2
smartmouse