Lambda Expression没有有效的最终变量

时间:2018-10-25 07:13:03

标签: java lambda java.util.concurrent functional-interface functional-java

我已经读到lambda表达式使用的外部变量必须是final或有效的final。 例如,如果我尝试在Supplier主体中修改外部String值,则编译器会按照上面的定义阻止我。 但是,如果我使用外部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;
  }
}

1 个答案:

答案 0 :(得分:4)

变量(有效)是最终变量,其字段不是。

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

最后一个变量意味着它不能被重新分配。示例:

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

不可变的变量表示其外部表示形式不会改变。这主要意味着其字段为final或有效地为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内容已更改,但是该变量本身从未重新分配,因为它不是重新分配,实际上是最终的决定。对namePojo的引用从未在您的代码中更改过,从而使它有效地成为最终