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();
        }

 

 

  • 9
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
lambda表达式中出现"Variable used in lambda expression should be final or effectively final"的问题,可以通过以下几种方式解决: 1. 将变量声明为final:将需要在lambda表达式中使用的变量声明为final,这样编译器就不会报错了。例如: ```java final int num = 10; Runnable r = () -> { System.out.println(num); }; ``` 2. 将变量声明为effectively final:如果变量lambda表达式中没有被修改,但没有被声明为final,可以将其声明为effectively finaleffectively final指的是变量在初始化后没有再被修改的情况。例如: ```java int num = 10; Runnable r = () -> { System.out.println(num); }; ``` 3. 使用局部变量的副本:如果需要在lambda表达式中修改变量的值,可以创建一个局部变量的副本,并在lambda表达式中修改副本的值。例如: ```java int num = 10; final int[] numCopy = {num}; Runnable r = () -> { numCopy[0] = 20; System.out.println(numCopy[0]); }; ``` 4. 使用AtomicInteger等线程安全的类:如果需要在lambda表达式中修改变量的值,并且需要保证线程安全,可以使用线程安全的类,如AtomicInteger。例如: ```java AtomicInteger num = new AtomicInteger(10); Runnable r = () -> { num.set(20); System.out.println(num.get()); }; ``` 总结起来,解决"Variable used in lambda expression should be final or effectively final"的问题可以通过将变量声明为finaleffectively final,使用局部变量的副本或使用线程安全的类来实现。这样就可以在lambda表达式中使用并修改变量的值了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值