简体   繁体   中英

The final local variable cannot be assigned, since it is defined in an enclosing type

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

If i write the above code Eclipse tells me this:

Cannot refer to a non-final variable vote inside an inner class defined in a different method

But if i add final before int vote it gives me this error:

The final local variable vote cannot be assigned, since it is defined in an enclosing type

So, how to solve?

Well, the standard trick is to use an int array of length one. Make the var final and write to var[0] . It is very important to make sure you don't create a data race. Using your code as an example:

final int[] vote = {0};

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

Since all this will be happenenig on the EDT, including the callback invocation, you should be safe. You should also consider using the anonymous class:

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

Move vote to 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();

EDIT

Or alternatively, pass a model class to the change listener

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 is used as follows:

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

我终于在主类中将声明声明为实例变量(私有)。

Setting the Compiler compliance level to 1.8 worked for me to solve a similar problem. I don't understand the reason but you may try this.

How it works:

Right click on the project --> Properties --> Java Compiler. And in java compiler properties window, set the compiler compliance level to 1.8.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM