据我了解,Java 没有真正的闭包。您可以通过 chaperoning 传递函数他们同一个类(class);然而,它不仅冗长而且(由于 Java 的内存模型)匿名类中对在构造它的环境中定义的变量的任何引用都作为 副本 传递。该语言通过仅允许匿名类引用 final
变量来鼓励我们记住这一点。
这让我想到了我在 Bloch 的 Effective Java 中找到的代码片段:
import java.util.concurrent.*;
public class StopThread {
private static boolean stopRequested;
public static void main(String[] args)
throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!stopRequested)
i++;
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
首先,我希望编译器会提示,因为 stopRequested
是非最终的,我在匿名类中引用它。我的编译器没有提示。
其次,我希望程序永远循环下去,因为 Java 不支持闭包,而且如果匿名类真的是从它构造的环境中引用实际的 stopRequested
变量(并且不是简单的副本)那么我们这里似乎有一个闭包。约书亚布洛赫还表示,该程序在他的计算机上永远循环。但是我的运行了大约一秒钟就退出了。
我误解了内存模型的哪一部分?
最佳答案
您缺少的关键是匿名类是嵌套类。因此,它具有对包含类实例的隐式引用,因此也是该类的成员。
只有局部变量需要final
才能被匿名类使用。
关于java - 匿名类中的非最终非局部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8120143/