提问人:Gonen I 提问时间:9/19/2021 最后编辑:Gonen I 更新时间:9/19/2021 访问量:60
Lambda 捕获的变量是否保证在 Lambda 的整个生命周期中存活?[复制]
Are Lambda Captured Variables Guarenteed To Survive Entire life of Lambda? [duplicate]
问:
这个问题在这里已经有答案了:
Java 中的异步 lambda 如何确定局部变量的范围 (1 个答案)
2年前关闭。
社区在 2 年前审查了是否重新打开这个问题,并将其关闭:
重复这个问题已经得到回答,不是唯一的,也没有与另一个问题区分开来。
在 Java 中,捕获的 lambda 变量的值可以在原始变量的作用域之外使用,如下所示:
interface MyInterface{
void doSomething( );
}
class Example {
MyInterface lambda;
public static void main(String[] args) {
Example e = new Example();
e.f1();
e.f2();
}
void f1() {
int local = 777;
lambda = () -> System.out.println(local);
}
void f2() {
lambda.doSomething(); // prints 777
}
}
匿名类也可以做到这一点。我怀疑实现会通过复制捕获本地值来做到这一点。
规范是否保证捕获的本地人能够像 lambda 一样长时间地生存?
我很想参考文档中的相关段落。(我搜索了一下,没有找到)
答:
1赞
rzwitserloot
9/19/2021
#1
我怀疑实现会通过复制捕获本地值来做到这一点。
正确。因为如果捕获的本地变量被修改,这将非常令人困惑,除非捕获的变量被标记为 [A] 或 [B] “有效最终”,否则将拒绝编译您的代码,这在规范中,这意味着:您可以将其标记为最终。javac
final
只要需要,此副本就会保留。一般来说,这些文档会保证除非你涉及 JNI,否则你无法在 java 中获得核心转储,而且垃圾回收规范不会比这更进一步。
1赞
Sweeper
9/19/2021
#2
在6.5.6.1中,据说(强调我的)
如果声明声明了一个最终变量,该变量在简单表达式之前明确赋值,则名称的含义是该变量的值。否则,表达式名称的含义是声明声明的变量。
因此,在您的 lambda 中表示 777,即您分配给 的(最终)值。这是通过复制您正确怀疑的变量来实现的。局部变量是否“存活”在这里并不重要。local
local
根据另一节,局部变量无法“生存”(4.12.3):
当局部变量的声明不再在作用域中时,局部变量将不复存在。
当您在 中运行 lambda 时,局部变量的声明超出了范围,因此它“不复存在”。f2
评论
final
final