lambda表达式提示变量错误:Variable used in lambda expression should be final or effectively final

今天在使用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();
        }
发布了38 篇原创文章 · 获赞 4 · 访问量 3182

猜你喜欢

转载自blog.csdn.net/qq_42107430/article/details/104551538
今日推荐