关于Java中局部final变量的问题
我有以下代码:
public class BookLib {
void f() {
final int x = 5; // Line 1
class MyCLass {
void print() {
System.out.println(x);
}
}
}
}
我不明白为什么在这种情况下应该使用 Final 变量(第 1 行)?
I have the following code:
public class BookLib {
void f() {
final int x = 5; // Line 1
class MyCLass {
void print() {
System.out.println(x);
}
}
}
}
I don't understand why should use final variable in this case (Line 1)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您已经在这里创建了一个内部类。由于此类对象的生命周期可能比方法调用的运行时间长得多(即,在方法返回后,对象仍然可以存在很长时间),因此它需要“保留”局部变量的状态可以访问。
这种保留是通过在内部类中创建一个(不可见的、合成的)副本并自动用对该副本的引用替换对局部变量的所有引用来完成的。当创建内部类对象后修改局部变量时,这可能会导致奇怪的效果。
为了避免这种情况,要求您以这种方式访问的所有局部变量都是
final
:这确保局部变量只有一个可能的值,并且不会观察到不一致的情况。此特定规则可以在 §8.1.3 内部类中找到以及 JLS 的封闭实例:
You've created an inner class here. Since the life-time of objects of this class can potentially be much greater than the runtime of the method invocation (i.e. the object can still exist long after the method has returned), it needs to "preserve" the state of local variables that it can access.
This preserving is done by creating an (invisible, synthetic) copy inside the inner class and automatically replacing all references to the local variable with references to that copy. This could lead to strange effects when the local variable were modified after the inner class object was created.
To avoid this, there is a requirement that all local variables that you access this way are
final
: this ensures that there is only ever one possible value for the local variable and no inconsistencies are observed.This specific rule can be found in §8.1.3 Inner Classes and Enclosing Instances of the JLS:
在这里您创建了一个内部类。为了访问执行上下文,对变量的引用应保持完整,否则会观察到错误行为。为了保证这一点,您应该将变量声明为final:这样就无法更改它。
请参阅此处的详细说明。
Here you create an inner class. In order to access the context of execution, the references to the variables should stay intact, otherwise an error behaviour is observed. In order to guarantee this, you should declare your variable final: thus one can't change it.
See detailed explanation here.
来自 kathy sierra scjp Book
方法的局部变量存在于堆栈中,并且仅在方法的生命周期内存在。我们已经知道,局部变量的作用域仅限于声明该变量的方法。当方法结束时,堆栈帧被吹走,该变量成为历史。但即使在该方法完成之后,在该方法中创建的内部类对象可能仍然存在于堆上,例如,如果将对它的引用传递到其他代码中,然后存储在实例变量中。由于不能保证局部变量与方法局部内部类对象一样长期存在,因此内部类对象无法使用它们。除非局部变量被标记为final!
From kathy sierra scjp Book
The local variables of the method live on the stack, and exist only for the lifetime of the method. We already know that the scope of a local variable is limited to the method the variable is declared in. When the method ends, the stack frame is blown away and the variable is history. But even after the method completes, the inner class object created within it might still be alive on the heap if, for example, a reference to it was passed into some other code and then stored in an instance variable. Because the local variables aren't guaranteed to be alive as long as the method-local inner class object, the inner class object can't use them. Unless the local variables are marked final!
所以你有一个局部最终变量和方法局部内部类。方法局部内部类不能使用方法内声明的非最终变量(包括参数)。
要更深入地探讨这一点:
方法局部内部类只能在定义该类的方法内实例化。局部变量在方法的生命周期内都存在于堆栈中。当方法结束时,局部变量消失,但是创建的内部类对象仍然存在。
这是生命周期/范围的问题。
So you have a local final variable and method-local inner class. A method-local inner class cannot use non-final variables declared within method (including parameters).
To go more deeply into this:
Method-local inner class can be instantiated only within method where the class is defined. The local variables live on stack for the lifetime of the method. As the method ends, the local variables disappear, however the inner class object created still lives.
It's a matter of lifetime/scope.