一、手动利用记事本编写Java测试代码
二、使用命令行进行编译
javac TestDemo.java
编译后会生成两个class文件
查看编译后的class文件
javap -p InterDemo.class
E:\test>javac TestDemo.java
E:\test>javap -p TestDemo.class
Compiled from "TestDemo.java"
public class TestDemo {
public TestDemo();
public static void main(java.lang.String[]);
private static void lambda$main$0(java.lang.String);
}
这里可以看到有一个构造方法,一个main方法,还有一个私有的静态方法,这个静态方法只要你使用都会生成,是一样的。
这个静态私有方法就是Lambda表达式中的方法实现。也就是Lambda表达式在底层构建中生成了一个
private static void lambda$main$0(java.lang.String message){
System.out.println(message);
}
这个私有静态方法什么时候被调用了呐?
我们对它内部生成的所有接口的源代码进行一个输出,通过如下代码我们可以查看TestDemo底层详细的编译过程
E:\test>java -Djdk.internal.lambda.dumpProxyClasses TestDemo
WangJun
这时你会发现文件夹中会生成一个TestDemo$$Lambda$1.class文件
我们对该文件字节码文件进行一个查看
E:\test>javap -p TestDemo$$Lambda$1.class
final class TestDemo$$Lambda$1 implements InterDemo {
private TestDemo$$Lambda$1();
public void markUp(java.lang.String);
}
可以看出Lambda表达式在编译的时候第一个是生成了一个私有的静态方法Lambda$main。
另外就是在构建时生成了一个内部类型:TestDemo$$Lambda$1.class
在这里边可以看到第一个是一个构造方法,第二个markUp的实现实际上就是调用了上边的私有静态方法。在调用静态方法的过程中将message传递了过来。
public void markUp(java.lang.String message){
TestDemo.lambda$main$0(message);
}
总结:
Lambda表达式在编译的过程中会生成一个私有的静态方法,在静态方法中做了一个方法的基本实现。
另外在编译的同时会针对Lambda表达式的目标接口,生成一个内部类型实现定义的接口,在实现这个接口的方法中完成对这个静态方法具体执行过程的调用
这两个方法在底层解析执行的时候其实他是在底层new 了一个当前内部类接口的对象,通过这个内部类接口的对象调用这个方法的marUp方法。
实际上Lambda表达式的运行过程可以理解为如下代码:
public class TestDemo{
public static void main(String [] args){
InterDemo inter=(string)->System.out.println(string);
inter.markUp("WangJun");
/**
new TestDemo$$Lambda$1().markUp("WangJun");
*/
}
}
/**
public class TestDemo {
public TestDemo();
public static void main(java.lang.String[]);
private static void lambda$main$0(java.lang.String){
System.out.println(message);
}
}
*/
/**
final class TestDemo$$Lambda$1 implements InterDemo {
private TestDemo$$Lambda$1();
public void markUp(java.lang.String){
TestDemo.lambda$main$0(java.lang.String message){
TestDemo.lambda$main$0(message);
}
}
}
*/
interface InterDemo{
void markUp(String string);
}