Конечная локальная переменная не может быть назначена, поскольку она определена в закрытом типе

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

Если я напишу приведенный выше код, Eclipse скажет мне следующее:

Нельзя ссылаться на голосование переменной без конечного значения внутри внутреннего класса определенные другим способом

Но если я добавлю final до int vote, это даст мне эту ошибку:

Конечное голосование по локальной переменной не может быть назначено, поскольку оно определено в закрывающемся типе

Итак, как решить?

Ответ 1

Ну, стандартный трюк - использовать массив int длиной один. Сделайте окончание var и напишите на var[0]. Очень важно убедиться, что вы не создаете гонку данных. Использование кода в качестве примера:

final int[] vote = {0};

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

Поскольку все это будет происходить в EDT, включая вызов обратного вызова, вы должны быть в безопасности. Вы также должны рассмотреть использование анонимного класса:

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

Ответ 2

Переместите vote в 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();

ИЗМЕНИТЬ

Или, наоборот, передайте класс модели слушателю изменений

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 используется следующим образом:

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

Ответ 3

Наконец, я решил объявить голосование как переменную экземпляра (private) в основном классе.

Ответ 4

Настройка уровня соответствия компилятора на 1.8 помогла мне решить подобную проблему. Я не понимаю причину, но вы можете попробовать это.

Как это работает:

Щелкните правой кнопкой мыши по проекту → Свойства → Компилятор Java. И в окне свойств java-компилятора установите для уровня соответствия компилятора значение 1.8.