1

为什么方法局部内部类不能使用在封闭方法中声明的变量,除了那些标记为final的变量,我知道在封闭方法中声明的变量可能会消失,而内部类实例仍然有效,但是当这个变量/ s 被宣布为最终的?

4

5 回答 5

2

原因是它在Java 语言规范 #8.1.3中指定

任何使用但未在内部类中声明的局部变量、形参或异常参数都必须声明为 final。

另请注意,旨在在 java 中引入闭包(以替换匿名类)的项目 lambda(java 8)引入了有效 final 的概念,这将允许您在 lambda 表达式中使用非 final 变量,只要您不这样做' t 在闭包内修改它。

于 2012-08-10T14:56:14.173 回答
1

原因是[实际上结论来自Java最终局部变量存储在哪里?] :final variables are copied by the compiler into a hidden member variable of the inner class that references it. This way, they are guaranteed to not change after the copy has been made.

也可能是:堆上的方法局部内部类和堆栈上的变量具有不同的范围。但是如果局部变量被final标记,它是存储在堆上的。

于 2012-08-10T14:45:28.570 回答
1

当变量为 final 时,将在内部类中放置一个副本。即它仍然无法访问该变量,但它有一个可以使用的副本。

如果您使用反射或调试器,您可以看到这些副本。

于 2012-08-10T14:52:14.783 回答
1

现在首先我想阐明

最终局部变量是否存储在堆而不是堆栈上?

说明:现在经过对 SO 的一些研究,我发现所有局部变量(最终或非最终变量)都存储到堆栈中,并且在方法执行结束时超出范围。

但是关于 final 变量JVM将这些作为常量,因为它们在启动后不会改变。并且当内部类尝试访问它们时,编译器会将该变量(不是它自身的变量)的副本创建到堆中 并在内部类中创建一个合成字段,因此即使方法执行结束它也可以访问,因为内部类有它自己的副本。合成领域文件实际上在源代码中不存在,但编译器在一些内部类中创建这些字段以使这些字段可访问。在简单的单词隐藏字段中。

所以最终变量也存储在堆栈中,但是内部类存储在堆中的那个变量的副本。

所以现在想一想。方法的局部变量存在于堆栈中,并且只在方法的生命周期内存在。我们已经知道,局部变量的作用域仅限于声明变量的方法。当方法结束时,栈帧被吹走,变量就是历史。但是即使在方法完成之后,在其中创建的内部类对象可能仍然在堆上存活,例如,如果对它的引用被传递到其他代码中,然后存储在实例变量中。因为只要方法局部内部类对象存在,局部变量就不能保证是存活的,所以内部类对象不能使用它们。除非局部变量被标记为final。将变量设为 final 是有益的,因为它可以像合成字段一样保持不变。

于 2016-02-29T19:28:32.173 回答
0

Final 确保您不会丢失对该变量的引用。您不希望您的内部类破坏或丢失您的引用,因为您可能会在声明的上下文中继续使用它。

于 2012-08-10T14:45:09.810 回答