Lambda中的变量捕获

问题描述 投票:0回答:1

我想不出为什么捕获的变量在lambda表达式中是final或有效的final。我查看了this question,但实际上并没有得到答案。

此变量捕获是什么?

当我寻找问题的解决方案时,我读到这些变量是最终的,因为存在并发问题。但是对于这种情况,为什么我们不能使用reentrant lock对象将任务代码锁定在lambda中。

public class Lambda {

  private int instance=0;

  public void m(int i,String s,Integer integer,Employee employee) {

    ActionListener actionListener = (event) -> {
      System.out.println(i);
      System.out.println(s);
      System.out.println(integer);
      System.out.println(employee.getI());
      this.instance++;
      employee.setI(4);
      integer++;//error
      s="fghj";//error
      i++;//error
    };
  }

}

在此特定代码中,我想知道最后三个语句为什么会出错,以及为什么要对Employee进行突变,因为它是局部变量。(Employee只是具有int i的getter和setter的类。 。)

而且我也想知道为什么我们也可以变异this.instance

我感谢我在上面提到的所有事实的详细答复。

java lambda final
1个回答
0
投票
由于并发问题,我读到这些变量是最终变量。
错误,这与并发无关,这与lambda(和匿名类)

“ capture”变量值的方式有关。

我想知道最后三个语句给出错误的原因

因为它们是

捕获,所以它们

必须有效地是最终的。

您真的不需要知道内部为什么要这样做,只需接受您需要遵守该规则的事实。

我想知道为什么我们可以变异this.instance

因为代码不是

capture instance,所以它是

captures this,并且this是隐式最终的。

原因
lambda主要是匿名类的语法糖。这不是真的,但出于解释的目的,这是足够正确的,对于匿名类,该解释更容易理解。

首先了解,JVM中没有匿名类之类的东西。实际上,也没有lambda表达式之类的东西,但这是另一回事。

但是,由于Java具有匿名类,因此编译器必须通过将匿名类转换为静态嵌套类来伪造它。

让我们以身作则。说我们有以下代码:

// As anonymous class int i = 0; Runnable run = new Runnable() { @Override public void run() { System.out.println(i); } } //As lambda expression: int i = 0; Runnable run = () -> System.out.println(i);

对于匿名类,编译器将生成这样的类:

static final class Anon_1 implements Runnable {
    private final int i;
    Anon_1(int i) {
        this.i = i;
    }
    @Override
    public void run() {
        System.out.println(i);
    }
}

然后将代码编译为:

int i = 0;
Runnable run = new Anon_1(i);

这就是

capture
的工作方式,通过

copying“ captured”变量的值。

变量根本不是captured,其值是,因为Java是构造函数调用中的按值传递。

现在您可以争论,没有理由为什么i应该是有效的最终值。当然,局部变量i和字段i现在是分开的,但是可以分别修改。

但是有,这是一个很好的理由。 i已被复制并且是分开的事实被完全隐藏,并且是实现细节。程序员会经常忘记这一点,并认为它们是相同的,这将导致许多失败的代码,并提醒您浪费大量的调试时间。

为了清楚起见,如果i局部变量为

captured

,并且匿名类中的i与外部的i

same,则必须为[]。 >要使其像这样[,局部变量

MUST

实际上是最终的,因此(内部)变量根本没有被捕获的事实与变量没有区别。运行代码。
© www.soinside.com 2019 - 2024. All rights reserved.