lambda表达式原理

public class Test {
    public static void main(String[] args) {
        Te te = new Te();
        te.sayHello(s -> {
            System.out.println("111111");
            System.out.println(s);
        });
    }
}
class Te{
    public void sayHello(Consumer consumer){
        consumer.accept(this);
    }
}
在Test类中,定义了一个内部类,其中sayHello接受一个函数式接口,因此在main方法调用采用lambda表达式可以代替匿名内部类来传递参数。

但是java可以支持传递一个函数形式的方式吗?lambda究竟是什么东西?(猜想传递过来的一定是Consumer的实现类)

通过一个参数设置一下,lambda表达式的保存路径

java -Djdk.internal.lambda.dumpProxyClasses d://

这里得到了一个jvm编译器生成的一个lambda类(Test$$Lambda$1)

import java.lang.invoke.LambdaForm.Hidden;
import java.util.function.Consumer;

// $FF: synthetic class
final class Test$$Lambda$1 implements Consumer {
    private Test$$Lambda$1() {
    }

    @Hidden
    public void accept(Object var1) {
        Test.lambda$main$0(var1);
    }
}

因此,在我们传递一个lambda表达式,实际上jvm帮我们在内存中生成了一个函数式接口的实现类,但是默认不保留在磁盘中

所以之前的调用类似于(因为构造被私有化了,但是相当于传递了一个实现类)

然后调用了Test$$Lambda$1.accept(Object var) 这个方法因为Consumer是消费性接口,需要在调用时传递一个参数,但是这个方法内部调用了一个方法是什么?

明显是一个Test类中生成的方法,但是这个方法是什么?先通过javap -p Test.class看一下是否有这个方法

明显编译器还给我们生成了一个方法,但是这个方法是什么内容呢,这里需要通过其他反编译工具来查看
CFR - yet another java decompiler. (benf.org) cfr下载地址
然后使用java -jar cfr-0.152.jar Test.class --decodelambdas false命令反编译一下
这里很明显看到,这个方法其实就是我们传递时的方法

总结:

一个lambda表达式,会在运行时生成两个东西,一个是在本类中的私有方法,一个是函数式接口的实现类

接受到这个接口实现类后,调用其实现的方法,方法里面会调用之前生成的私有方法,

其实和动态代理差不多,代理目标类就是Test$$Lambda$1,在实现方法中调用需要代理的方法(代理方法就是lambda表达式转化的lambda$main$0(Object var)方法,InvocationHandler等同于调用函数接口的类)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值