鉴于此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
而不是因为final
缺少param
而没有编译,或者只是打印:
initial
initial
我记得在将参数传递给匿名类时要求final
,但在Java 7中似乎并非如此。改变了什么?
答案 0 :(得分:3)
没有任何改变。外部类的字段始终可供内部类访问。只有在从内部类访问局部变量时才需要final。
在Java 8中,即使是局部变量也不需要被声明为final。它们必须简单地有效最终,即编译器足够聪明,可以检查它们是否永远不会被重新分配。
打印的内容完全正常,因为内部类只是对外部类实例的引用,并且访问其字段的方式与外部类中的方法相同。
答案 1 :(得分:3)
在8.1.3节中定义:
其声明不在静态上下文中出现的内部类可以自由引用其封闭类型声明的实例变量。
它的工作方式很简单:编译器为你的内部类生成一个构造函数,并将封闭实例的引用传递给该构造函数。只要内部类引用已解析为封闭类成员的变量,就可以通过构造对象时存储的引用进行访问。
封闭类的成员变量不需要final
。该要求仅适用于本地变量,这些变量被捕获"在创建内部类的对象时。