前一段时间在CSDN论坛回答的一个问题,觉得蛮有意思的,决定拿出来在这里记录一下。
问题的提出:
该例子程序涉及到了三个class文件,分别是Contents.java,Destination.java,Parcel10.java。其中的Contents.java和Destination.java是两个interface,而Parcel10.java是含有静态内部类的一个类文件。
具体代码如下:
Contents.java
Destination.java
Parcel10.java
编译Parcel10.java得到了如下的class文件:
Contents.class
Destination.class
Parcel10$1.class
Parcel10$PContents.class
Parcel10$PDestination$AnotherLevel.class
Parcel10$PDestination.class
Parcel10.class
这里面的Parcel10$1.class到底是怎么产生的?程序里面并没有匿名内部类。
分析:
先把代码编译出来,然后用javap -c来反编译以下Parcel10,看看有什么特别。
发现以下两段很刺眼,我们看到了那个神奇的Parcel10$1。
Parcel10$PDestination(java.lang.String, Parcel10$1);
和
Parcel10$PContents(Parcel10$1);
而Parcel10$PDestination和Parcel10$PContents的构造函数被javac私改了。
所以可以断定,其实这个Parcel10$1是编译器为了某种原因而自己创建的。
那这个Parcel10$1什么情况下会出现呢?
解答:
好了,不想卖关子了。记忆中,这个问题有好几次都被误提为java:compiler的一个bug,但都被invalid掉了。
Parcel10$1是编译器用来限制权限用的,构建了一个假的构造函数来达到你上面private静态内部类。
而他到底出不出现,是要看,
1、内部类的构造函数是不是私有的?
2、这个内部类的私有构造函数有没有被调用,如果只是定义了这个构造函数,但是没有被调用过,这个奇怪的Parcel10$1不会出现。
另外,这是Java编译器的内部问题,并不是每一个编译器都会产生这个Parcel10$1,有些网友用eclipse就没有看到,我们可以用javap -c看看eclipse自动编译出来后的Parcel10,
本文的论坛原帖子《阅读thinking in java遇到了一个内部类的小问题》。
可以料想,只要这个奇怪的构造函数被调用,那编译器就需要为他的决定买单,自己生成这个奇怪的class。