问题描述
关于编译器错误的堆栈溢出有一些主题不能引用在不同方法
中定义的内部类中的非最终变量消息,解决方案是声明它是最终的并且你已经完成了,但是对于这个理论问题,我想检查一下这个代码无法编译的逻辑原因是什么:
There are some topics on Stack Overflow on the compiler error Cannot refer to a non-final variable message inside an inner class defined in a different method
and the solution is "declare it as final and you're done", but with this theoretical question I would like to inspect what is the logical reason why this code cannot compile:
private void updateStatus(String message) {
Runnable doUpdateStatus = new Runnable() {
public void run() {
/* do something with message */
}
}
/* do something with doUpdateStatus, like SwingUtilities.invokeLater() */
}
(解决方案:声明消息
作为最终),而这一行:
(solution: declare message
as final) whereas this one does:
private String enclosingClassField;
private void updateStatus() {
Runnable doUpdateStatus = new Runnable() {
public void run() {
/* do something with enclosingClassField */
}
}
/* do something with doUpdateStatus, like SwingUtilities.invokeLater() */
}
我真的很困惑。 enclosingClassField
不是最终的,它可以每次都改变很多次,而消息
的参数 updateStatus
只能在其方法体内更改,而是由编译器指责;)
I'm really confused. enclosingClassField
is not final, it can change every time many times, whereas the poor message
argument of updateStatus
can only change within its method body, and is instead blamed by the compiler ;)
即使编译器错误也会误导我。 不能引用以不同方法定义的内部类中的非最终变量消息
:与什么不同?不是消息
在与内部类相同的方法中定义?是不是 enclosingClassField
而是在方法外定义?嗯...
Even the compiler error is misleading to me. Cannot refer to a non-final variable message inside an inner class defined in a different method
: Different from what? Isn't message
defined in the same method as the inner class? Isn't enclosingClassField
instead defined outside the method? Uhm...
有人能指出我对此事的正确解释吗?谢谢。
Can someone point me to the correct interpretation of this matter? Thanks.
推荐答案
区别在于本地(方法)变量与类成员变量之间。成员变量在封闭对象的生命周期中存在,因此它可以由内部类实例引用。但是,局部变量仅在方法调用期间存在,并且由编译器以不同方式处理,因为它的隐式副本是作为内部类的成员生成的。在没有声明局部变量final的情况下,可以更改它,导致细微的错误,因为内部类仍然引用该变量的原始值。
The difference is between local (method) variables vs class member variables. A member variable exists during the lifetime of the enclosing object, so it can be referenced by the inner class instance. A local variable, however, exists only during the method invocation, and is handled differently by the compiler, in that an implicit copy of it is generated as the member of the inner class. Without declaring the local variable final, one could change it, leading to subtle errors due to the inner class still referring to the original value of that variable.
更新 更详细地讨论了这一点。
Update: The Java Specialists' Newsletter #25 discusses this in more detail.
我相信内部类'运行
方法。
这篇关于为什么非最终的“本地”变量不能在内部类中使用,而是封闭类的非final字段可以吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!