问题解决思路:查看编译生成的字节码文件
本文本来我是发布在博客园,现在移植到CSDN;原文链接
思路一:
- 编译
javac fileName.java
- 反编译
javap -v -p fileName.class
; 这一步可以看到字节码。
思路二:
运行阶段保留jvm生成的类
java -Djdk.internal.lambda.dumpProxyClasses fileName.class
不错的博客:https://blog.csdn.net/zxhoo/article/category/1800245
本人旨在探讨匿名内部类、lambda表达式(lambda expression),方法引用(method references )的底层实现,包括实现的阶段(第一次编译期还是第二次编译)和实现的原理。
测试匿名内部类的实现
建议去对照着完整的代码来看 源码链接
基于strategy类,使用匿名内部类,main函数的代码如下,称作test1
Strategy strategy = new Strategy() {
@Override
public String approach(String msg) {
return "strategy changed : "+msg.toUpperCase() + "!";
}
};
Strategize s = new Strategize("Hello there");
s.communicate();
s.changeStrategy(strategy);
s.communicate();
第一步:现在对其使用javac编译,在Strategize.java的目录里,命令行运行javac Strategize.java
,结果我们可以看到生成了5个.class文件,我们预先定义的只有4个class,而现在却多出了一个,说明编译期帮我们生成了一个class,其内容如下:
class Strategize$1 implements Strategy {
Strategize$1() {
}
public String approach(String var1) {
return var1.toUpperCase();
}
}
第二部:对生成的 Strategize.class
进行反编译,运行javap -v -c Strategize.class
,在输出的结尾可以看到下面信息:
NestMembers:
com/langdon/java/onjava8/functional/Strategize$1
InnerClasses:
#9; // class com/langdon/java/onjava8/functional/Strategize$1
说明,这个Strategize$1
的确是Strategize
的内部类。
这个类是命名是有规范的,作为Strategize
的第一个内部类,所以命名为Strategize$1
。如果我们在测试的时候多写一个匿名内部类,结果会怎样?
我们修改main()方法,多写一个匿名内部类,称做test2
Strategy strategy1 = new Strategy() {
@Override
public String approach(String msg) {
return "strategy1 : "+msg.toUpperCase() + "!";
}
};
Strategy strategy2 = new Strategy() {
@Override
public String approach(String msg) {
return "strategy2 : "+msg.toUpperCase() + "!";
}
};
Strategize s = new Strategize("Hello there");
s.communicate();
s.changeStrategy(strategy1);
s.communicate();
s.changeStrategy(strat