Lambda 捕获实例变量

2023-12-07

在一次令人沮丧的调试会话后阅读 JLS,我发现 lambda 会捕获value有效最终局部变量,但如果您引用实例变量,它会捕获对该变量的引用,这对多线程代码有严重影响。

例如,以下是从一个更大的程序中提取的 MCVE:

public class LambdaCapture
{
    public static void main(String[] args) throws Exception
    {
        Launcher i1 = new Launcher();
        i1.launchAsynchTask();
    }

    public static class Launcher
    {
        private int value = 10;

        public void launchAsynchTask() throws Exception
        {
            System.out.printf("In launchAsynchTask value is %s\n",value);
            Thread t = new Thread(()->doSomething(value));
            t.start();
            value = -1;
            t.join();
        }

        public void doSomething(int value)
        {
            System.out.printf("In asynch task, value is %s\n",value);
        }
    }
}

我发现输出令人惊讶。这是

In launchAsynchTask value is 10
In asynch task, value is -1

因为我最初(在 JLS 研究之前)并直觉地期望 lambda 能够捕获value变量的value而不是对其的引用。

如果我必须保证当前value被捕获而不是引用,明显的解决方案是创建一个本地最终临时:

        final int capture = this.value;
        Thread t = new Thread(()->doSomething(capture));

我的问题:这是强制获取价值的公认惯用方式,还是有其他更自然的方式来做到这一点?


我……直觉地期望 lambda 捕获变量值的值而不是对其的引用。

这(捕获值)就是局部变量发生的情况。

对于字段,实际发生的是您正在捕获对该字段所属对象实例的引用。就您而言,它是对Launcher.this目的。 (当您声明内部类时,也会发生同样的事情。)

我的问题:这是强制获取价值的公认惯用方式,还是有其他更自然的方式来做到这一点?

我想不出更好的办法了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Lambda 捕获实例变量 的相关文章

随机推荐