【问题标题】:Variable should be final inside listener [duplicate]变量在侦听器中应该是最终的[重复]
【发布时间】:2012-06-10 15:08:29
【问题描述】:

可能重复:
Cannot refer to a non-final variable inside an inner class defined in a different method
Why are only final variables accessible in anonymous class?

在 SO 和谷歌中寻找这个问题的答案,但找不到任何答案。

我有以下代码:

MyClass variable = new MyClass();
Button b = new Button();
b.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent e){
         System.out.println("You clicked the button");
         variable.doSomething();
   }
});

编译器返回这个:

局部变量变量是从内部类中访问的;需要 被宣布为最终的

variable 必须是 final 的技术原因是什么?

【问题讨论】:

  • 感谢您的链接。没有解释为什么编译器是这样设计的。为什么内部类不引用外类并在需要时访问变量,而不是在第一次实例化时引用?
  • @GETah:如果变量是一个成员,那你就说得通了。但它是本地的。您不能依赖它定义的堆栈帧仍然存在,并且在 Java 中没有对变量的引用这样的东西。所以如果你想使用它,你几乎必须复制一份。

标签: java


【解决方案1】:

这是因为您使用的是匿名内部类。 发生的是编译器为您创建类。它将它称为您的外部类并添加$ 和数字,例如$$2

该类具有自动初始化的外部类的引用,因此其实例可以使用外部类的方法和字段。

但是你的班级是匿名的。它是在方法内部定义的,可以使用在这个匿名类之前定义的 its 内部变量。问题是“它怎么能做到?”确实,您不能参考“运行方法的实例”来访问其变量。答案是匿名内部类引用的所有方法变量都复制到匿名内部类。因此变量必须是最终的:否则有人可以从外部类更改它们的值,并且这些更改对内部类是不可见的。

【讨论】:

    【解决方案2】:

    这是因为内部类仅在触发事件时才执行代码。如果变量没有声明为final,那么variable中引用的MyClass对象可能会发生变化,如果内部类需要MyClass对象,它将不知道应该引用哪个Object。

    因此,它应该被声明为 final,所以这个引用永远不会改变。

    想象一下没有 final 关键字:

    variable 正在使用 hashCode(): 12345 引用 MyClass 对象 内部类被创建,内部类中的variable 引用MyClass 对象与hashCode(): 12345

    variable 更改为现在使用 hashCode(): abcde 引用 MyClass 对象 内部类中的variable 仍在使用hashCode(): 12345 引用MyClass 对象

    当事件被触发时,Java 如何从这里运行代码?使用哪个MyClass 对象?

    现在使用 final 关键字:

    variable 正在使用 hashCode(): 12345 引用 MyClass 对象 内部类被创建,内部类中的variable 引用MyClass 对象与hashCode(): 12345

    由于final关键字,引用不能改变。

    Java 总是知道在触发事件时要调用哪个 MyClass 对象。没问题。

    【讨论】:

    • 所以编译器不够聪明,无法知道它设置在外部类的某个位置?
    • 我不认为这个答案是正确的。 “最终”要求适用于所有变量,而不仅仅是引用的变量。
    • @Jochen 是正确的。原语也会出现同样的问题。线程缓存原始变量和引用变量。
    • 同样的问题。如果原始变量在内部类之外被更改,那么它不会反映在内部类中。因此,它应该被宣布为最终的。
    • 内部类可能有一个对外部类的引用,并使用它来访问正确的variable
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多