匿名 class 如何访问父 class 的参数?

How does an anonymous class access parent class' parameters?

鉴于此 SSCE:

public class AnonymousClassTest {

    String param = "initial";

    void test() {
        Runnable runnalbe = new Runnable() {
            @Override
            public void run() {
                System.out.println(param);
            }
        };
        runnalbe.run();

        param = "after";

        runnalbe.run();
    }

    public static void main(String[] args) {
        new AnonymousClassTest().test();
    }

}

任何人都可以指出 JLS 或任何其他文档中的一部分来解释为什么结果是

initial
after

而不是因为 param 缺少 final 而没有编译,或者只是打印:

initial
initial

我记得在将参数以这种方式传递给匿名 class 时需要 final,但在 Java 中似乎并非如此 7. 发生了什么变化?

没有任何变化。外部 class 的字段始终可供内部 class 访问。仅当从内部 class.

访问 局部变量 时才需要 final

在 Java8 中,即使是局部变量也不需要声明为 final。它们必须只是有效最终的,即编译器足够聪明,可以检查它们是否从未被重新分配。

打印的内容完全正常,因为内部 class 只是引用了外部 class 实例,并且访问其字段的方式与外部 [=21= 的方法相同] 就可以了。

8.1.3节中定义:

Inner classes whose declarations do not occur in a static context may freely refer to the instance variables of their enclosing type declaration.

它的工作方式很简单:编译器为您的内部 class 创建构造函数,并将封闭实例的引用传递给该构造函数。每当您的内部 class 引用已解析为封闭 class 成员的变量时,将通过在构造对象时存储的引用进行访问。

不要求class的成员变量必须是final。该要求仅适用于局部变量,在创建内部 class 的对象时是 "captured"。