当前位置: 首页 > 面试题库 >

为什么不能在内部类内部使用非最终的“局部”变量,而可以在封闭类中使用非最终的字段呢?

唐恺
2023-03-14
问题内容

关于编译器错误Cannot refer to a non-final variable message inside an inner class defined in a different method,有一些关于Stack
Overflow的主题,解决方案是“将其声明为最终的,您就完成了”,但是对于这个 理论性的 问题,我想检查一下该代码无法编译的逻辑原因是什么:

private void updateStatus(String message) {
    Runnable doUpdateStatus = new Runnable() {
         public void run() {
             /* do something with message */
         }
    }
    /* do something with doUpdateStatus, like SwingUtilities.invokeLater() */
}

(解决方案:声明message为final),而这一点却做到了:

private String enclosingClassField;
private void updateStatus() {
    Runnable doUpdateStatus = new Runnable() {
         public void run() {
             /* do something with enclosingClassField */
         }
    }
    /* do something with doUpdateStatus, like SwingUtilities.invokeLater() */
}

我真的很困惑
enclosingClassField不是最终值,它可以多次更改,而的可怜message参数updateStatus只能在其方法体内更改,而是由编译器负责;)

甚至编译器错误也误导了我。Cannot refer to a non-final variable message inside an inner class defined in a different method
与什么不同?message与内部类不是在同一方法中定义的吗?是不是enclosingClassField该方法之外,而不是定义?嗯…

有人可以指出我对此事的正确解释吗?谢谢。


问题答案:

区别在于局部(方法)变量与类成员变量之间。成员变量在封闭对象的生存期内存在,因此可以由内部类实例引用。但是,局部变量仅在方法调用期间存在,并且由编译器以不同方式处理,因为它的隐式副本作为内部类的成员生成。如果不将局部变量声明为final,则可以对其进行更改,由于内部类仍在引用该变量的原始值,从而导致细微的错误。

更新:
Java专家通讯25号对此进行了更详细的讨论。

甚至编译器错误也误导了我。Cannot refer to a non-final variable message inside an inner class defined in a different method与什么不同?

run我相信从内层阶级的方法。



 类似资料:
  • 本地风险值背后的想法是最终的,而领域不是。

  • 在此代码示例中,ActionListener的actionPerformed函数中没有使用最终对象jLabel:

  • 问题内容: 我有按钮单击侦听器,并且在方法中我有一个局部变量,例如 为什么Java要求让我最终决定? 问题答案: 当onCreate()方法返回时,您的局部变量将从堆栈中清除,因此它们将不再存在。但是匿名类对象new View.OnClickListener()引用了这些变量。当然,这是错误的行为,因此Java不允许您执行此操作。 最终确定后,它将成为一个常数。因此它存储在堆中,可以在匿名类中安全

  • 问题内容: 我想知道使用最终局部变量是否有可用性。当继承出现时,变量无论如何都不会被覆盖。例如下面的简单代码 这个例子很简单,可能不是一个相关的代码,但是问题比较笼统。我已经看到了很多代码(全部都包含在具有最终局部变量的main函数中)是否有将局部变量声明为final other的可用性。不能在同一功能中进行编辑? 问题答案: 首先,关于变量被“覆盖”的部分具有两个非常不同的含义。对于类和方法,它

  • 我正在写一个程序,我得到这样的结果:“最后的局部变量asd不能被赋值,因为它是在一个封闭类型中定义的”。 我将提供一个示例,它不是来自我的代码,但这也会产生错误。我有一个arraylist,我想以后在按钮之外使用它(如果我在按钮内部定义它,以后就不能使用它了),但是按下按钮应该会给这个arraylist提供值。在本例中,它将“创建一个新的ArrayList”,这将导致同样的问题。