【问题标题】:Is there any way to change value captured by Java Lambda有什么方法可以改变 Java Lambda 捕获的值
【发布时间】:2018-05-04 02:01:12
【问题描述】:

类似这样的:

    Integer value = 3;
    Consumer<Integer> consumer = input -> {
        value = value * 2;
    };
    consumer.accept(100);
    System.out.println(value);

谢谢! [已解决]

    AtomicInteger value = new AtomicInteger(3);
    Consumer<Integer> consumer = input -> {
        value.getAndAdd(5); // 8
        System.out.println(value.get());
    };
    consumer.accept(100);
    System.out.println(value.get()); // 8

也感谢 Umer Farooq 的回答 Modifying local variable from inside lambda

【问题讨论】:

标签: java lambda


【解决方案1】:

不,这是不可能的。

JLS 15.27.2 说:

在 lambda 表达式中使用但未声明的任何局部变量、形式参数或异常参数必须声明为 final 或有效 final(第 4.12.4 节),否则在尝试使用时会发生编译时错误。

由于您在 lambda 中使用 value,但在 lambda 之外声明它,它必须是最终的或有效的最终。这意味着您不能多次为其赋值。

当然,如果value 是一个可变对象(例如AtomicInteger),那么您能够改变它。 value 引用本身不会改变,但它引用的对象会改变。

【讨论】:

    【解决方案2】:

    因此,由于 Java 编译器只允许在 lambda 或匿名内部类中访问最终或成员引用,因此答案是否定的。但是,您可以(正如您似乎已经发现的那样)更改最终引用中的状态。

    您找到了使用 AtomicInteger 的解决方法,当您修改 Integer 时,该解决方法适用于您的特定情况。将您的引用放在最终的单值数组中将适用于所有内容。它不是很漂亮,但如果您使用IntelliJ,如果您尝试在这种情况下修改最终状态,它会为您提供此更改。

    这是一个例子:

    final int[] value = { 3 };
    Consumer<Integer> consumer = input -> {
        value[0] = value[0] * 2;
    };
    consumer.accept(100);
    System.out.println(value[0]);
    

    【讨论】:

      猜你喜欢
      • 2018-05-26
      • 2020-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-29
      • 1970-01-01
      • 2019-05-01
      • 2014-07-23
      相关资源
      最近更新 更多