首先看一下代码:
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<>();
}
}