1、现象
1 | public class Lanting { |
这段代码没什么特点,就是在startTest中创建并开启了一个线程,里面需要注意的是 其中的Runnable部分是直接用的lambda表达式。
然后,我在用javap命令( javap -v Lanting.class
)查看Lanting.class文件时,发现了如下的东西:

使用 jclasslib Bytecode Viewer 插件查看class文件结构如下:

可以看到,Lanting这个类编译器自己创建了一个静态方法lambda$startTest$0()
并且用了synthetic
修饰。
使用反射动态获取Lanting所有的方法再试试,结果如下:

可以看到,确实动态生成了lambda$startTest$0()
方法。
2、结论
经过尝试,发现以下几点规则:
- 方法名的生成规则满足一个模板:
lambda$使用lambda表达式的方法名$方法内的lambda序号
- 如果lambda中用到了this关键字,那么生成的方法就不是静态的,如果没用到,生成的方法就是静态的
- 实际我们使用lambda表达式时,不会生成内部类,而只是生成一个方法,在JVM调用的时候,实际调用的是该方法
- 如果lambda中使用到了上层方法中的局部变量,生成的方法的形参就包含该类型,例如,有以下代码:
1 | public class Lanting { |
可以看到,lambda表达式用到了name局部变量,这个变量是在lambda外面创建的,从而,自动生成的代码则会多一个形参:

实际调用的时候,是通过这个形参传递过去,并且形参为final的。