当访问作为引用的类成员时,lambda 表达式是否保留对其封闭实例的引用?

x-r*_*ray 5 java lambda reference

我认为描述我的问题的最简单方法是举一个例子:

class Enclosing {
    private ObjectOfInterest o = new ObjectOfInterest();
    public void registerEventListener() {
        EventEmitter.onEvent(() -> {
            // Need to access 'o' here, while 'this' is not important.
            o.yeeha();
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

lambda 表达式是否包含对其实例的隐式引用Enclosing?如果是这样,我该如何避免这种情况以避免内存泄漏?我需要访问o事件侦听器,但不需要访问封闭的实例。

顺便说一句,我发现了这个问题“ Java8 lambda 是否像匿名类一样维护对其封闭实例的引用? ”,但我不清楚 lambda 表达式何时被认为“不从封闭实例捕获成员”。此外,接受的答案中引用的文档声明自己已过时。

use*_*125 5

您的 lambda 必须维护对 的引用Enclosing,因为该字段的值可能在 lambda 创建和执行之间发生更改。如果将下一个代码添加到末尾registerEventListener

o = null;
Run Code Online (Sandbox Code Playgroud)

然后您将期望您的事件侦听器失败并显示NullPointerException。因此它必须持有对 的引用this

this另外我应该提到的是,即使该字段是,它也必须保持对 的引用final,因为它的值仍然可以在反射的帮助下更改。

但是,如果您只需要使用在创建 lambda 时设置的值,那么您可以创建一个局部变量并在 lambda 中使用它:

public void registerEventListener() {
    final ObjectOfInterest currentO = this.o;
    EventEmitter.onEvent(() -> {
        currentO.yeeha();
    });
}    
Run Code Online (Sandbox Code Playgroud)