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等同于调用函数接口的类)