Java 引用非最终变量:为什么要编译此代码?
首先,如果这是一个重复的问题,我道歉。我发现了许多类似的问题,但没有一个能直接解决我的问题 为了准备即将到来的考试,我正在做一篇过去的论文。它有一个问题,给出了一个代码片段。我们必须说明它是否编译,如果不编译,写第一个编译器错误发生的行并解释它。以下是代码片段:Java 引用非最终变量:为什么要编译此代码?,java,java-8,inner-classes,Java,Java 8,Inner Classes,首先,如果这是一个重复的问题,我道歉。我发现了许多类似的问题,但没有一个能直接解决我的问题 为了准备即将到来的考试,我正在做一篇过去的论文。它有一个问题,给出了一个代码片段。我们必须说明它是否编译,如果不编译,写第一个编译器错误发生的行并解释它。以下是代码片段: public static void main(String[] args) { JFrame f = new JFrame("hi"); JTextField jtf = new JTextField(50);
public static void main(String[] args) {
JFrame f = new JFrame("hi");
JTextField jtf = new JTextField(50);
jtf.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent evt) {
jtf.setText(evt.getLocationOnScreen().toString());
}
});
f.add(jtf);
f.setVisible(true);
}
我希望它不会编译为jtf
不是final
。我通过在Eclipse中输入上面的代码来测试我的理论,该代码标记了预期的错误,但编译并运行良好。只有在将鼠标滑过JTextField
之后,我才得到了预期的错误:
java.lang.Error:未解决的编译问题:
无法引用在封闭范围中定义的非最终局部变量jtf
我进行了一些搜索,发现Eclipse使用了自己版本的Java编译器。因此,我在Eclipse之外重新创建了该文件,并通过命令行编译/运行它。它编译时没有错误或警告,当鼠标移到文本字段上时,显示所需的java.awt.Point[x=…,y=…]
我对匿名内部类的理解是,它们可以访问:
- 封闭类的字段
- 封闭类的方法
- 封闭范围的局部变量,前提是它们是
final
那么我错过了什么?据我所知,这段代码不应该工作。Java8添加了访问变量的功能。只要变量在初始化后从未更改,就不再需要
final
关键字。我猜您是在用Java 8编译。在这里,您的jtf
变量实际上是最终变量,因此它可以很好地编译。如果在初始化变量后其值从未更改,则该变量实际上是最终变量
另见:
但是,从JavaSE8开始,本地类可以访问本地类
封闭块的最终或最终变量和参数
实际上是最终的。其值从不为零的变量或参数
初始化后更改的内容实际上是最终的
及
与本地类一样,匿名类可以捕获变量;他们有
对封闭范围的局部变量具有相同的访问权限:
- 匿名类可以访问其封闭类的成员
- 匿名类无法访问其封闭类中的局部变量 未声明为最终或有效最终的范围
javac -source 1.7 MyFile.java
您将得到预期的错误
.java:13: error: local variable jtf is accessed from within inner class; needs to be declared final
jtf.setText(evt.getLocationOnScreen().toString());
^
1 error
因此,考试问题的答案是:只有在使用Java 8+时,它才会编译。它可能在
Java8
中工作,因为重点是有效的Final
,这意味着一旦将值分配给jtf
之后就不应该更改。根据Java文档:
一种变量或参数,其值在输入后不会改变
初始化实际上是最终的
您的EclipseIDE似乎使用Java7编译器。要将其更改为Java 8,请使用项目->属性->Java编译器->编译器符合性级别