Java Lambda的变量捕获

如果曾经使用过C++的Lambda表达式,那么就会知道C++有一个变量捕获列表

有两种捕获方式,一种是引用捕获,一种是变量捕获。与C++函数的传引用、传值相对应。

而Java与C++不同 ,java只有引用捕获

例如:

        ScheduledExecutorService ses = Executors.newScheduledThreadPool(5);

        int a=0;

        for(int i=1;i<=10;i++){

            ses.schedule(()->{

                System.out.println(a);

            },i,TimeUnit.MILLISECONDS);

        }

通过编译

 

        ScheduledExecutorService ses = Executors.newScheduledThreadPool(5);

        int a=0;

        for(int i=1;i<=10;i++){

            ses.schedule(()->{

                System.out.println(a);

            },i,TimeUnit.MILLISECONDS);

        }

  a=1;

编译失败

 

那么此时我们可以输出i吗? 答案是不可以的

因为i并不final

那么如何才能输出变量i

i作为field是否可以呢?

    private int i = 0;

    public void run(){

       ScheduledExecutorService ses = Executors.newScheduledThreadPool(5);

       for(i=1;i<=10;i++){

           ses.schedule(()->{

              System.out.println(i);

           },i,TimeUnit.MILLISECONDS);

       }

    }

编译通过,结果不正确

输出10个 “11”

这是因为执行计划任务的时候 i已经变了。这也说明java不是值捕获。

此时可以创建final的变量作为跳板,帮助我们实现此功能

        ScheduledExecutorService ses = Executors.newScheduledThreadPool(5);

        for(int i=1;i<=10;i++){

            final int curi=i;

            ses.schedule(()->{

                System.out.println(curi);

            },i,TimeUnit.MILLISECONDS);

        }

 

为什么这样声明就可以了呢?

在创建lambda表达式的时候,lambda用到的外部引用都被复制了一份(因为局部变量在栈内存中,稍后会被销毁)。

 

这样看来java的lambda在需要捕获基础类型值的场景下,不如C++灵活

而final的限制,可以减少人为的错误

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值