内部类和lamdba 引用最终变量(final)做更新操作

我们知道内部类使用外部变量时,需要的是一个不可变的量(final),但有时因为 final 限制显得并不太方便,如:我们想要在一个封闭作用域中设计一个计时器,如我们想要计算排序过程中的调用 compareTo的次数,那该怎么解决,一般我们是这么写:

    public static void main(String[] args) {
        int counter = 0;
        Date[] dates = new Date[100];
        for (int i = 0; i < dates.length; ++i){
            dates[i] = new Date() {
                @Override
                public int compareTo(Date other) {
                    counter++; // error
                    return super.compareTo(other);
                }
            };
        }
        Arrays.sort(dates);
        System.out.println(counter);
    }

很简单的逻辑,但这种写法是错误的,在内部类种,不可引用可变的量,由于我们清楚的知道 counter 是需要更新的,所以不能讲 counter 声明为 final, 由于 Interger 对象也是不可变,所以并不能用Integer代替它,虽然我们可以设计一个类来存储一个Integer值,但这显得多余,补救的方法就是使用一个长度为1的数组:

    public static void main(String[] args) {
        final int[] counter = {0};
        Date[] dates = new Date[100];
        for (int i = 0; i < dates.length; ++i){
            dates[i] = new Date() {
                @Override
                public int compareTo(Date other) {
                    counter[0]++;
                    return super.compareTo(other);
                }
            };
        }
        Arrays.sort(dates);
        System.out.println(counter[0]);
    }

为什么可以这样做呢,因为数组其实也是实现了Object对象,数组本身就是一个对象,couter 在这里实际是存放着地址单位,因为数组的地址一旦创建除非手动改动,之后都是不会放松变化,所以可以用数组来代替。
实际上在 java8 中 Collectors 类新增的大量汇聚方法中都运用了此类解决方法,因为在 lamdba 表达式中,捕获的变量必须实际上是最终变量

public static <T> Collector<T, ?, Integer>
    summingInt(ToIntFunction<? super T> mapper) {
        return new CollectorImpl<>(
                () -> new int[1],
                (a, t) -> { a[0] += mapper.applyAsInt(t); },
                (a, b) -> { a[0] += b[0]; return a; },
                a -> a[0], CH_NOID);
    }

这里说明一下,lambda可以替代内部类,但 lamdba 与 内部类 本质上是两个不同的东西。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值