Java 无法分配最终局部变量,因为它是在封闭类型中定义的

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21485590/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 08:57:43  来源:igfitidea点击:

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

javainner-classesfinal

提问by smartmouse

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:

如果我写了上面的代码,Eclipse 会告诉我:

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

不能在不同方法中定义的内部类中引用非最终变量投票

But if i add finalbefore int voteit gives me this error:

但是如果我在int 投票之前添加final,它会给我这个错误:

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

无法分配最终局部变量 vote,因为它是在封闭类型中定义的

So, how to solve?

那么,如何解决呢?

回答by Marko Topolnik

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:

嗯,标准技巧是使用长度为 1 的 int 数组。将 var 设为 final 并写入var[0]. 确保不会造成数据竞争非常重要。以您的代码为例:

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:

由于所有这些都将在 EDT 上发生,包括回调调用,因此您应该是安全的。您还应该考虑使用匿名类:

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

回答by Peter Keller

Move voteto SliderMoved:

移动voteSliderMoved

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
}

Personis used as follows:

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

回答by smartmouse

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

我终于解决了在主类中将投票声明为实例变量(私有)的问题。

回答by Nadeem

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.

将编译器合规性级别设置为 1.8 对我来说解决了类似的问题。我不明白原因,但你可以试试这个。

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.

右键单击项目--> 属性--> Java 编译器。并在 java 编译器属性窗口中,将编译器合规性级别设置为 1.8。