Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 663
smartmouse Avatar asked Jan 31 '14 16:01

smartmouse


3 Answers

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(); }
});
like image 120
Marko Topolnik Avatar answered Nov 11 '22 18:11

Marko Topolnik


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();
like image 5
Peter Keller Avatar answered Nov 11 '22 18:11

Peter Keller


I finally solved declaring vote as instance variable (private) in the main class.

like image 2
smartmouse Avatar answered Nov 11 '22 19:11

smartmouse