Java-在Lambda中更改最终变量的值 [英] Java - changing the value of a final variable from within a lambda

查看:536
本文介绍了Java-在Lambda中更改最终变量的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java中,我有以下代码

In Java I have the following code

List<Integer> myList = new ArrayList<>();
for (int i=0;i<9;i++) {
    myList.add(i);
}

Integer sum = 0;

myList.forEach(i -> {
    sum = sum + i; // does not compile, sum needs to be final or effectively final
});   

for(int i : myList) {
    sum = sum + i; //runs without problems
} 

我的问题是,为什么我不能从lambda内更改sum的值呢?它与下面的for循环完全相同,还是我错了?有趣的是,如果我在main方法之外将Integer sum声明为static,它也可以正常工作.谁能解释我为什么?

My question is, why is it exactly that I cannot change the value of sum from within the lambda? It does the exact same thing as the for loop down below, or am I wrong? Interesting is also the fact that if I declare the Integer sum outside of the main method as static, it works as well. Can anyone explain me why?

在另一个类似的问题 Java 8是否支持闭包,答案似乎成为:

In another similar question Does Java 8 support closures, the answer seems to be :

它是向后兼容性和项目资源限制的结合.

it is a combination of backwards compatibility and project resourcing constraints.

但是,如果我使sum成为数组或在main之外声明它,我仍然无法理解为什么它可以工作.我还想了解myList.forEach和下面的for循环之间的区别,为什么一个可以工作而另一个不能工作.

However I still cannot understand why it works if I make sum an array or if I declare it outside of main. I would also like to understand what is the difference between the myList.forEach and the for loop below, why the one works and the other one doesn't.

推荐答案

尝试使用:

final Integer[] sum = new Integer[1];
sum[0] = 0;

myList.forEach(i -> {
    sum[0] = sum[0] + i; // does not compile, sum needs to be final or effectively final
}); 

因为lambda实际上是用于初始化匿名类(并覆盖方法)的语法糖.

Since lambda is actually a syntactic sugar for initializing an anonymous class (and overriding a method).

就跟您写的一样:

final Integer[] sum = new Integer[1];
sum[0] = 0;

myList.forEach(new Consumer() {
    public void accept(Integer element) {
        sum[0] = sum[0] + element;
    }
});

来自外部作用域的变量以及您在内部作用域中使用的变量必须是最终变量(在此示例中为sum).这仅仅是因为Java不支持闭包.因此,外部变量必须标记为final.由于Integer本身是不可变的(如果将其声明为final,则无法再对其进行更改),因此必须使用包装对象或数组(如我所做的那样).

The variable that comes from outer scope and that you use within inner scope must be final (in this example sum). That is simply because Java does not support closures. Therefore, outer variable must be marked as final. Since Integer itself is immutable (if you declare it final, you cannot change it anymore), you have to use a wrapper object or an array (as I did).

您可以在此处找到更多有用的信息:

You can find more useful info here:

  • Why are only final variables accessible in anonymous class?
  • Cannot refer to a non-final variable inside an inner class defined in a different method

这篇关于Java-在Lambda中更改最终变量的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆