1

我读过 lambda 表达式使用的外部变量必须是最终的或有效的最终的。例如,如果我尝试修改供应商主体中的外部字符串值,编译器会阻止我,就像上面的定义一样。但是如果我使用外部 Pojo(修改它的属性 - 所以它的内部状态),那么它可以正常工作并否定上面的声明。

怎么会?

package com.quicktutorialz.test;

import java.util.function.Supplier;

public class MainApplication {

  public static void main(String[] args){

    // MY NON-EFFECTIVELY-FINAL POJO
    NamePojo namePojo = new NamePojo();
    namePojo.setName("Luisa");

    //MY LAMBDA
    Supplier<String> supplier = () -> {
        namePojo.setName("Alex");  //HOW IS THAT POSSIBLE?!?!
        return "Hello " + namePojo.getName();
    };

    System.out.println(supplier.get());


  }
}

class NamePojo {
  String name;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }
}
4

1 回答 1

4

该变量(实际上)是最终的,它的字段不是。

您正在混合最终变量和不可变变量。

final 变量意味着它不能被重新分配。例子:

void doSomething() {
  int a = 0;  // is effectively final
  int b = 1;  // is not effectively final
  b = 2;
}

不可变变量意味着它的外部表示不会改变。这主要意味着它的字段是final或实际上是最终的。例子:

class A {
  int value;
  A(int value) { this.value = value; }
  int getValue() { return this.value; }
}

public void doSomething() {
  A a = new A(0);
  // no way to change a.value
}

在你的情况下:

public class MainApplication {

  public static void main(String[] args){

    // MY NON-EFFECTIVELY-FINAL POJO
    NamePojo namePojo = new NamePojo();    // namePojo is assigned.
    namePojo.setName("Luisa");             // namePojo is changed, but not reassigned.

    //MY LAMBDA
    Supplier<String> supplier = () -> {
      // namePojo is changed, but not reassigned.
      namePojo.setName("Alex");  //HOW IS THAT POSSIBLE?!?!
      return "Hello " + namePojo.getName();
    };

    System.out.println(supplier.get());

  }
}

变量的内容namePojo更改,但变量本身永远不会重新分配,因为它没有重新分配,它实际上是最终的。在您的代码中对 never changed 的​​引用namePojo,使其有效地成为 final

于 2018-10-25T07:15:23.647 回答