Java中Effectively Final变量失效求助:累加结果始终为0
问题分析与解决方法
你的问题核心在于BigDecimal是不可变类,add()方法不会修改调用它的对象本身,而是返回一个全新的BigDecimal实例。
你当前的代码里,total.add(product.getPrice())只是计算了临时的总和,但没有把这个新实例关联到total变量——初始的total是BigDecimal.ZERO,且属于effectively final变量,无法在lambda表达式中重新赋值,所以最终返回的始终是初始值0。
正确实现方式
方式一:使用Stream的reduce方法(推荐)
这是最简洁且符合函数式编程风格的写法:
public BigDecimal getTotalAmount() { return products.stream() .map(Product::getPrice) .reduce(BigDecimal.ZERO, BigDecimal::add); }
方式二:使用AtomicReference处理可变引用(仅作理解用)
如果一定要用forEach,需要借助AtomicReference来包装BigDecimal,它可以在lambda中安全更新引用:
import java.util.concurrent.atomic.AtomicReference; public BigDecimal getTotalAmount() { AtomicReference<BigDecimal> totalRef = new AtomicReference<>(BigDecimal.ZERO); products.forEach(product -> { totalRef.updateAndGet(current -> current.add(product.getPrice())); }); return totalRef.get(); }
关键要点
- 记住BigDecimal的所有修改方法(
add/subtract/multiply等)都不会改变原对象,必须接收返回的新实例才能得到更新后的值。 - lambda表达式中引用的外部变量必须是effectively final的,因此无法直接给原
total变量重新赋值,这也是第一种stream reduce方式更合适的原因。
内容的提问来源于stack exchange,提问作者DEV
相关产品推荐
相关产品推荐

