forEach中提示Copy xxx to effectively final temp variable原因

首先看一下代码:

public class Test {

    public static void main(String[] args) {

        List<Integer> list1 = new ArrayList<>();
        List<Integer> list2 = new ArrayList<>();
        Arrays.asList(1,2,3).forEach(e->{
            list1.add(e);
            list2.add(e);
        });

        list1 = new ArrayList<>();

    }

}

看起来没什么问题,就是通过forEach的形式遍历1,2,3数组,并将其添加到list1和list2中,唯一的区别在于,list1在添加完之后又重新赋值了一个新值。但是当我们运行或者再idea中会发现,在list1.add这里会报红波浪线,提示Copy xxx to effectively final temp variable即叫我们要拷贝list1到一个final变量去使用,但是为什么list2不会报红呢?

要解释这个问题,首要要了解下forEach,forEach方法接受一个Consumer类型的入参,而Consumer是一个接口,也就是我们传入的e->{}其实相当于是使用匿名类的形式来把代码操作传给forEach执行,这也就是lambda的写法。重点在于,在lambda中,如果要引用外层局部变量的话,这个变量需要被定义为final类型。但是为什么list2没问题呢?这是因为在java8中,我们可以偷懒省略这个final。

所以上述代码相当于

public class Test {

    public static void main(String[] args) {

        List<Integer> list1 = new ArrayList<>();
        final List<Integer> list2 = new ArrayList<>();
        Arrays.asList(1,2,3).forEach(e->{
            list1.add(e);
            list2.add(e);
        });

        list1 = new ArrayList<>();

    }

}

而为什么list1是在forEach中报红呢?因为在代码中存在list1重新赋值,所以java不会认为list1是个final类型的变量,所以会提示:Copy xxx to effectively final temp variable,假如我们给list1也手动指定上final,就会发现报红的地方变了。

public class Test {

    public static void main(String[] args) {

        final List<Integer> list1 = new ArrayList<>();
        final List<Integer> list2 = new ArrayList<>();
        Arrays.asList(1,2,3).forEach(e->{
            list1.add(e);
            list2.add(e);
        });

        list1 = new ArrayList<>();

    }

}


文章太有用啦👍,打赏个钢镚鼓励鼓励!!