Java 从内部访问的局部变量 class;需要声明为 final,为什么它在 NetBeans 中有效?
Java local variable accessed from within inner class; needs to be declared final, why it works in NetBeans?
在我的 Java 应用程序中,有一个方法,它具有以下代码:
JButton Button = new JButton(Content);
Button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
doSomething(Button.getText());
}
});
它在 NetBeans 8.1 中编译并运行良好,但今天当我尝试从命令行编译该项目时,出现以下错误:
local variable Button is accessed from within inner class; needs to be declared final
我的问题是:为什么相同的代码在 NetBeans 8.1 中兼容并运行良好,但不能在命令行中编译?
我的命令行Java版本是:1.8.0_77
而我的 NetBeans Java 版本是:1.8.0_65
这应该无关紧要,那么为什么 NetBeans 不认为这是一个错误呢?
编辑:哇,对我来说是个大惊喜,我刚刚检查了 javac:
C:\Users\USER>java -版本
java 版本“1.8.0_77”
C:\Users\USER>javac -版本
javac 1.7.0_40
等一下,我 100% 很困惑,首先我不知道有一个 "javac -version" 命令,我以为 "java -verison" 会告诉我 java 和 javac,我假设它们是相同的,其次,当我安装 Java 时,我以为安装程序会自动更新它,而 javac 是 java 的一部分,所以它应该在内部是一致的,但它绝对不是,所以我的 java -version 与我的 javac -version 有什么不同?换句话说,我怎么能相信 Oracle 同时安装我的 java 和 javac,如果它没有完成工作,这是否意味着每次我更新 Java,我需要以某种方式手动安装我的 javac 吗?我从来没有这样做过,所以为什么会发生这种情况?
在Java8之前,所有需要在内部class中访问的局部变量都需要声明final
。这是由于一个实现细节——局部变量被实现为内部 class 的隐藏实例变量。如果可以更改变量,则内部 class 中的副本将不正确。
在 Java 8 中,此要求放宽为 "final" 或 "effectively final"(向下滚动大约 2/3 的方式)。
However, starting in Java SE 8, a local class can access local variables and parameters of the enclosing block that are final or effectively final. A variable or parameter whose value is never changed after it is initialized is effectively final.
变量不必显式声明为 final
,它只需有效地声明为最终的——不显式 final
,只是未更改。
你没有改变 Button
,所以它实际上是最终的,它在 Java 8 下编译。但是,Java 7 仍然要求它被显式声明 final
所以有一个编译器错误。
修复您的路径,使 javac
成为您的 Java 8 安装。您可能安装了 Java 8 的 JRE(无 "javac" 可执行文件),但安装了 JDK 1.7 (Java 7),这可以解释您的版本控制输出。在这种情况下,您需要下载并安装 Java 8 JDK (1.8).
在我的 Java 应用程序中,有一个方法,它具有以下代码:
JButton Button = new JButton(Content);
Button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
doSomething(Button.getText());
}
});
它在 NetBeans 8.1 中编译并运行良好,但今天当我尝试从命令行编译该项目时,出现以下错误:
local variable Button is accessed from within inner class; needs to be declared final
我的问题是:为什么相同的代码在 NetBeans 8.1 中兼容并运行良好,但不能在命令行中编译?
我的命令行Java版本是:1.8.0_77
而我的 NetBeans Java 版本是:1.8.0_65
这应该无关紧要,那么为什么 NetBeans 不认为这是一个错误呢?
编辑:哇,对我来说是个大惊喜,我刚刚检查了 javac:
C:\Users\USER>java -版本 java 版本“1.8.0_77”
C:\Users\USER>javac -版本 javac 1.7.0_40
等一下,我 100% 很困惑,首先我不知道有一个 "javac -version" 命令,我以为 "java -verison" 会告诉我 java 和 javac,我假设它们是相同的,其次,当我安装 Java 时,我以为安装程序会自动更新它,而 javac 是 java 的一部分,所以它应该在内部是一致的,但它绝对不是,所以我的 java -version 与我的 javac -version 有什么不同?换句话说,我怎么能相信 Oracle 同时安装我的 java 和 javac,如果它没有完成工作,这是否意味着每次我更新 Java,我需要以某种方式手动安装我的 javac 吗?我从来没有这样做过,所以为什么会发生这种情况?
在Java8之前,所有需要在内部class中访问的局部变量都需要声明final
。这是由于一个实现细节——局部变量被实现为内部 class 的隐藏实例变量。如果可以更改变量,则内部 class 中的副本将不正确。
在 Java 8 中,此要求放宽为 "final" 或 "effectively final"(向下滚动大约 2/3 的方式)。
However, starting in Java SE 8, a local class can access local variables and parameters of the enclosing block that are final or effectively final. A variable or parameter whose value is never changed after it is initialized is effectively final.
变量不必显式声明为 final
,它只需有效地声明为最终的——不显式 final
,只是未更改。
你没有改变 Button
,所以它实际上是最终的,它在 Java 8 下编译。但是,Java 7 仍然要求它被显式声明 final
所以有一个编译器错误。
修复您的路径,使 javac
成为您的 Java 8 安装。您可能安装了 Java 8 的 JRE(无 "javac" 可执行文件),但安装了 JDK 1.7 (Java 7),这可以解释您的版本控制输出。在这种情况下,您需要下载并安装 Java 8 JDK (1.8).