在一次令人沮丧的调试会话后阅读 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(使用前将#替换为@)