a
在这里只能是最终的。为什么?如何在a
方法中重新分配onClick()
而又不将其保留为私有成员?
private void f(Button b, final int a){
b.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
int b = a*5;
}
});
}
单击
5 * a
时如何返回?我的意思是,private void f(Button b, final int a){
b.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
int b = a*5;
return b; // but return type is void
}
});
}
最佳答案
如注释中所述,其中某些在Java 8中变得无关紧要,其中final
可以隐式包含。但是,只能在匿名内部类或lambda表达式中使用有效的最终变量。
这基本上是由于Java管理closures的方式。
创建匿名内部类的实例时,该类中使用的任何变量都将通过自动生成的构造函数复制其值。这样避免了编译器不得不自动生成各种额外的类型来保存“局部变量”的逻辑状态,例如C#编译器确实...(当C#在匿名函数中捕获变量时,它实际上捕获了变量-闭包可以通过该方法的主体看到的方式更新变量,反之亦然。)
由于该值已被复制到匿名内部类的实例中,因此如果变量的其余部分可以被该方法的其余部分修改,则看起来会很奇怪-您可能会看到代码似乎在使用过期的变量(因为这实际上是将要发生的事情……您将使用在不同时间拍摄的副本)。同样,如果您可以在匿名内部类中进行更改,则开发人员可能希望这些更改在封闭方法的正文中可见。
将变量设为final消除了所有这些可能性-由于根本无法更改该值,因此您无需担心此类更改是否可见。允许方法和匿名内部类相互查看更改的唯一方法是使用某种描述的可变类型。这可能是封闭的类本身,一个数组,一个可变的包装器类型……诸如此类。基本上,这有点像一种方法与另一种方法之间的通信:调用者看不到对一个方法的参数所做的更改,但可以看到对参数所引用的对象所做的更改。
如果您想对Java和C#闭包之间的更详细的比较感兴趣,请参考article。我想在此答案中专注于Java方面:)
关于java - 为什么在匿名类中只能访问最终变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49249185/