为什么方法本地内部类不能使用在封闭方法中声明的变量,除了那些标记为final的变量,我知道在封闭方法中声明的变量可能会在内部类实例保持有效时消失,但是当这个变量/ s被声明为final?
答案 0 :(得分:2)
原因是它在Java Language Specification #8.1.3
中指定使用但未在内部类中声明的任何局部变量,形式参数或异常参数必须声明为final。
另请注意,项目lambda(java 8)旨在在java中引入闭包(以替换匿名类),引入了有效final的概念,这将允许您在lambda表达式中使用非final变量,只要你不要在闭包内修改它。
答案 1 :(得分:1)
原因是[Where are Java final local variables stored?]的实际结论: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.
也可能是:堆上的Method-Local Inner Class和堆栈上的变量具有不同的范围。但是如果局部变量由final标记,则它存储在堆上。
答案 2 :(得分:1)
当变量为final时,副本将放在内部类中。即它仍然无法访问变量,但它有一个可以使用的副本。
如果使用反射或使用调试器,则可以看到这些副本。
答案 3 :(得分:1)
现在我首先想谈谈
最终的局部变量是否存储在堆而不是堆栈中 ?
说明:现在经过SO的一些研究后发现所有本地变量(最终或不)都存储在堆栈中并且去了出 方法执行结束时的范围。
但是关于最终结果 变量JVM
将这些变为常量,因为它们不会在之后发生变化 发起了。当一个内部类尝试访问它们时编译器创建 该变量的副本(不是它自己的变量)进入堆 并在内部类中创建合成字段,所以即使在 方法执行结束,因为内部类是可访问的 有自己的副本。提交的合成字段实际上并不存在 存在于源代码中,但编译器在某些字段中创建这些字段 内部类使这些字段可访问。用简单的词隐藏起来 场。
所以最终变量也存储在堆栈中,但是内部类存储在堆中的变量。
所以现在考虑一下。该方法的局部变量存在于堆栈中,仅存在于方法的生命周期中。我们已经知道局部变量的范围仅限于声明变量的方法。当方法结束时,堆栈帧被吹走,变量是历史。但即使在方法完成之后,在其中创建的内部类对象仍可能在堆上存活,例如,如果对它的引用被传递到其他代码中,然后存储在实例变量中。因为只要方法本地内部类对象,局部变量不能保证存活,所以内部类对象不能使用它们。除非局部变量标记为final。并且它是有益的使变量最终,因为它可以保持像合成领域。
答案 4 :(得分:0)
Final确保您不会丢失对该变量的引用。您不希望内部类破坏或丢失您的引用,因为您可能会在声明的上下文中继续使用它。