Java 停止在内部类中的非最终变量上出错 (java 8)

2022-09-01 17:00:06

Java 7在以下代码中说“不能引用在封闭作用域中定义的非最终局部变量消息”:

public class Runner {   
    public static void main(String[] args) {

        String message = "Hello world";

        new Runnable() {
            @Override
            public void run() {
                System.out.println(message);
            }
        }.run();
    }
}

Java 8 没有。

怀疑这是关于向Java添加函数式编程功能。

它是否以类似的方式处理代码?


答案 1

Java 8 隐式地使 final 变得 final,因为它永远不会被修改。尝试在代码中的任何位置修改它,您将收到编译错误(因为这会删除隐式)。messagefinal

这被称为有效的最终。引用自文档

但是,从 Java SE 8 开始,局部类可以访问封闭块的局部变量和参数,这些变量和参数是最终的或实际上是最终的。如果变量或参数的值在初始化后永远不会更改,则该变量或参数实际上是最终的。


答案 2

Java 8(和Lambdas)引入了有效的最终术语:即使你没有用关键字来定义它,如果它没有被修改,它也和final一样好。final

引用自 Oracle Tutorial: Local Classes

但是,从 Java SE 8 开始,局部类可以访问封闭块的局部变量和参数,这些变量和参数是最终的或实际上是最终的。如果变量或参数的值在初始化后永远不会更改,则该变量或参数实际上是最终的。

您的消息实际上是最终消息,因此从匿名内部类和 lambda 引用它是有效的。

如果更改消息的值,它将不再是有效的最终值

String message = "Hello world";
new Runnable() {
    @Override
    public void run() {
        System.out.println(message);
    }
}.run();
message = "modified";

因此,您会收到以下错误(来自 Eclipse):

在封闭作用域中定义的局部变量消息必须是最终消息或实际上是最终消息

或形式 :javac

错误:从内部类引用的局部变量必须是最终变量或实际上是最终变量


推荐