今天在使用lambda表达式时,遇到一个问题。
Variable used in lambda expression should be final or effectively final
代码如下:
/**
* @ClassName: CyclicBarrierDemo
* @description:
* @author: XZQ
* @create: 2020/2/28 10:31
**/
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(6, () -> {
System.out.println("召唤神龙");
});
for (int i = 1; i <= 7; i++)
new Thread(() -> {
System.out.println("继承第" + i+ "颗龙珠");
}, String.valueOf(i)).start();
}
}
}
为什么 Lambda 表达式(匿名类) 不能访问非 final 的局部变量呢? 因为实例变量存在堆中,而局部变量是在栈上分配,Lambda 表达(匿名类) 会在另一个线程中执行。如果在线程中要直接访问一个局部变量,可能线程执行时该局部变量已经被销毁了,而 final 类型的局部变量在 Lambda 表达式(匿名类) 中其实是局部变量的一个拷贝。
通俗点说就是,为了避免匿名子线程开始了之后,还没有执行到System.out.println("继承第" + i+ "颗龙珠");之前,父线程就把i的值改变了,这时候得到的结果就和我们预期的不一样了,而我们又需要不断改变i的值,解决方法其实很简单,就是要使得子线程里用到的值都不要发生变化嘛,再定义一个变量,将i的值赋给它,然后再线程里用到这个变量就行了。
修改如下
for (int i = 1; i <= 7; i++) {
int finalI = i;
new Thread(() -> {
System.out.println("继承第" + finalI + "颗龙珠");
}, String.valueOf(i)).start();
}