Local Classes的Java文档说:
此外,本地类可以访问局部变量。但是,一个 本地类只能访问声明为final的局部变量。 当本地类访问本地变量或参数时 封闭块,它捕获该变量或参数。例如, PhoneNumber构造函数可以访问本地变量numberLength 因为它被宣布为最终的; numberLength是一个捕获的变量。
什么是捕获变量,它的用途是什么以及为什么需要它?请帮助我理解它的概念。
答案 0 :(得分:16)
什么是捕获变量,它的用途是什么以及为什么需要它?
捕获的变量是已复制的变量,因此可以在嵌套类中使用。它必须被复制的原因是对象可能在当前上下文中存活。它必须是final
(或在Java 8中有效final
),因此不会混淆是否会看到对变量的更改(因为它们不会)
注意:Groovy确实有这个规则,对局部变量的更改可能意味着更改封闭类中的值,如果涉及多个线程,这将特别令人困惑。
捕获变量的一个例子。
public void writeToDataBase(final Object toWrite) {
executor.submit(new Runnable() {
public void run() {
writeToDBNow(toWrite);
}
});
// if toWrite were mutable and you changed it now, what would happen !?
}
// after the method returns toWrite no longer exists for the this thread...
答案 1 :(得分:2)
捕获的变量是来自本地类外部的变量 - 一个在周围的块中声明。在某些语言中,这称为closure.
在the Oracle Docs(简化)的示例中,“捕获”了变量numberLength,在PhoneNumber类中声明外部。
final int numberLength = 10; // in JDK7 and earlier must be final...
class PhoneNumber {
// you can refer to numberLength here... it has been "captured"
}
答案 2 :(得分:2)
这是一篇描述它的帖子:http://www.devcodenote.com/2015/04/variable-capture-in-java.html
以下是该帖子的摘录:
“Java强制要求,如果方法中定义的内部类引用该方法的局部变量,则应将该局部变量定义为final。”
这是因为函数可能完成执行并从进程堆栈中删除,所有变量都被销毁,但可能是内部类的对象仍然在堆上引用该函数的特定局部变量。为了解决这个问题,Java制作了局部变量的副本,并将其作为对内部类的引用。为了保持2个副本之间的一致性,本地变量被强制为“最终”且不可修改。