Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 引用非最终变量:为什么要编译此代码?_Java_Java 8_Inner Classes - Fatal编程技术网

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编译器->编译器符合性级别