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

博客介绍了Java中内部类使用外部变量时,因final限制带来不便的问题。以计算排序中compareTo调用次数为例,提出用长度为1的数组替代的解决方法,并解释了原理。还提到Java 8中Collectors类汇聚方法运用此方法,以及Lambda可替代内部类但本质不同。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们知道内部类使用外部变量时,需要的是一个不可变的量(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 与 内部类 本质上是两个不同的东西。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值