【问题标题】:Lambda Expression works with no effectively final variable [duplicate]Lambda 表达式在没有有效最终变量的情况下工作 [重复]
【发布时间】:2019-03-29 17:16:24
【问题描述】:

我了解到 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;
  }
}

【问题讨论】:

  • namePojo 变量实际上是最终变量。

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


【解决方案1】:

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

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

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内容更改,但变量本身永远不会重新分配,因为它没有重新分配,它实际上是最终的。对namePojo 的引用从未在您的代码中更改,使其实际上是最终的

【讨论】:

  • 我读到:“一个有效的最终变量是其值在首次分配后不会改变的变量。”我分配了 namePojo 及其内部状态,然后更改了它
  • 另外,对象引用的值是被引用的地址,而不是对象本身。因此,引用后面的对象是可修改的。引用本身不可修改,即不可重新签名。
猜你喜欢
  • 2015-12-18
  • 2018-09-15
  • 2016-08-23
  • 1970-01-01
  • 2018-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-08
相关资源
最近更新 更多