lambda表达式引用的本地变量必须是final的。

5

我正在尝试从一个使用详细信息类值的POJO中创建getValue()函数,其意义如下:

@Transient
public BigDecimal getValue() {
   BigDecimal sum = new BigDecimal(0);

   details.stream().forEach((detail) -> {
      sum = sum.add(detail.getValue());
   });

   return sum;
}

但我不知道为什么这行代码 sum = sum.add(detail.getValue()); 会引发以下错误:

从 lambda 表达式引用的局部变量必须是 final 或有效 final

请问您能告诉我我做错了什么吗?谢谢。

1
错误信息很明确:如果您想从lambda中访问本地变量(sum),则必须将其声明为final。因此,您不能按照您展示的方式进行,必须另寻他法。 - T.J. Crowder
没错,我发表了一个回答说过了这个问题,但后来意识到仍然不起作用,因为他试图修改sum。 - Enwired
但是,如果我像“final”一样声明局部变量sum,那么我会得到下一个错误:“无法为最终变量sum分配值”。 - axiorema
@axiorema 正确。Lambda表达式将不允许您像这样修改局部变量。 - Louis Wasserman
3个回答

15

在lambda表达式内部,您无法修改变量。这不是允许您执行的操作。

在此处可以做的是将此方法编写为

return details.stream()
    .map(Detail::getValue)
    .reduce(BigDecimal.ZERO, BigDecimal::add);

哦,非常有趣,我会尝试理解这个的 ;) 谢谢 - axiorema
这是一个非常有启发性的答案,我从中学到了很多。我喜欢mapreduce函数。谢谢。 - axiorema

4

好的,在foreach循环中不要使用lambda表达式。

@Transient
public BigDecimal getValue() {
   BigDecimal sum = new BigDecimal(0);

   for (Detail detail : details) {
      sum = sum.add(detail.getValue());
   }

   return sum;
}

1
这是我避免循环中的最终p的方法,它确实起到了作用。
public void getSolutionInfo(){      
ArrayList<Node> graph = Main.graph; 

    for(int p=1;p<=Pmax;p++) {          
        final int p2=p;
        System.out.printf("number of node with priority p = %d is %d ",p, graph.stream().filter(node->node.getPriority()==p2).count()); 
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接