why I cannot refer to a non-final variable inside an inner class defined in a different method?
为什么我不能引用在不同方法中定义的内部类中的非最终变量?
我看过关于这个的主题,大多数人都说您的组件应该是最终的,而且……但是没人说为什么?!!!我不知道这一限制背后的哲学是什么。
更让我困惑的是以下代码是错误的:
1 2 3 4 5 6 7 8 9 10 | JButton removeJBtn = new JButton("Remove"); JButton addJBtn = new JButton("Add"); //... btnNewButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { removeJBtn.disable();//Error here,Cannot ... } }); |
如果我定义
1 | JButton removeJBtn |
作为成员字段(在类的主体中,不是方法),不需要定义为final!
对于我(可能还有许多其他人)一直面临的每日限制,我真的很感激任何合乎逻辑的答案。
亲爱的用户,如果将此问题标记为副本,请至少参考原始问题(已确定答案!)在我的问题上面加了一个链接,我读得很透彻,但是它充满了矛盾,有些人(有88张选票)说Java捕获了最终变量的值,它完全被下面的评论(16票)否决了。
方法的局部变量位于堆栈上,并且仅存在于方法的生存期。您已经知道局部变量的作用域是仅限于变量声明的方法。当方法结束时,堆栈框架被吹走,变量是历史。但即使在方法之后完成后,在堆中创建的内部类对象可能仍然在堆中活动,如果,例如,对它的引用被传递到其他代码中,然后存储在实例变量。因为局部变量不能保证活得那么久作为方法局部内部类对象,内部类对象不能使用它们。除非局部变量被标记为final!
资料来源:Kathy Sierra SCJP
扩展其他答案,您应该记住,匿名类是语法Java糖,以防止您创建具体的类,并在每次您必须提供一个按钮侦听器时实例化它们——如果您想这样做(您可以轻松地跳过匿名类,而不用具体的类来替换它们)没有问题。您必须通过构造函数将值(这里是
因为普通变量只存在于堆栈上(在您的例子中是指向对象的指针)。由于内部类可以(通常也可以)比定义方法寿命长,因此变量将不再存在。
通过使变量成为最终变量,编译器可以创建优化(在本例中:将最终变量作为"秘密"成员包含在内部类中)。如果变量不是最终变量,这将是无效的,因为它可能在之后更改。