java为什么匿名内部类不包含从该代码生成的任何内容?
package com.test;
public class OuterClass {
public class InnerClass {
public class InnerInnerClass {
}
}
public class InnerClass2 {
}
//this class should not exist in OuterClass after dummifying
private class PrivateInnerClass {
private String getString() {
return "hello PrivateInnerClass";
}
}
public String getStringFromPrivateInner() {
return new PrivateInnerClass().getString();
}
}
在命令行上用Sun JVM 1.6.0_20
运行javac
时,此代码生成6。类文件:
OuterClass.class
OuterClass$1.class
OuterClass$InnerClass.class
OuterClass$InnerClass2.class
OuterClass$InnerClass$InnerInnerClass.class
OuterClass$PrivateInnerClass.class
在eclipse中运行JDT时,它只生成5个类
OuterClass.class
OuterClass$1.class
OuterClass$InnerClass.class
OuterClass$InnerClass2.class
OuterClass$InnerClass$InnerInnerClass.class
OuterClass$PrivateInnerClass.class
反编译时,OuterClass$1.class
不包含任何内容。这个额外的课程是从哪里来的?为什么创建它
# 1 楼答案
我用的是Polygene的小片段
记住字节码中没有嵌套类的概念;然而,字节码知道访问修饰符。编译器试图回避的问题是 方法
instantiate()
需要创建PrivateInnerClass
的新实例。但是,OuterClass
无权访问PrivateInnerClass
的构造函数(OuterClass$PrivateInnerClass
将作为包保护类生成,而不使用公共构造函数)那么编译器能做什么呢?显而易见的解决方案是将
PrivateInnerClass
更改为具有包保护的构造函数。这里的问题是,这将允许与该类接口的任何其他代码创建PrivateInnerClass
的新实例,即使它显式声明为private为了防止这种情况发生,javac编译器正在做一个小技巧:它没有使
PrivateInnerClass
的常规构造函数在其他类中可见,而是将其隐藏(实际上它根本没有定义它,但从外部看也是一样)。相反,它创建了一个新的构造函数,该构造函数接收特殊类型OuterClass$1
的额外参数现在,如果你看一下
instantiate()
,它会调用新的构造函数。它实际上将null
作为第二个参数(类型为OuterClass$1
)发送——该参数仅用于指定应调用的构造函数那么,为什么要为第二个参数创建一个新类型呢?为什么不使用,比如说,
Object
?它只用于将其与常规构造函数区分开来,而且null
无论如何都会被传递!答案是,由于OuterClass$1
对OuterClass是私有的,合法的编译器永远不会允许用户调用特殊的OuterClass$PrivateInnerClass
构造函数,因为所需的参数类型之一OuterClass$1
是隐藏的我猜JDT的编译器使用了另一种技术来解决同样的问题
# 2 楼答案
还有一个点——如果用户已经声明了
OuterClass$1
,那么OuterClass$PrivateInnerClass
无论如何都会将其作为构造函数参数:-
# 3 楼答案
搜索后我找到了这个链接http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6378717
注释指的是给定链接中可用的源代码
# 4 楼答案
根据Polygene的答案,我猜这个神秘的类会阻止其他任何人(即
OuterClass
之外的人)实例化OuterClass$PrivateInnerClass
,因为他们没有访问OuterClass$1
的权限# 5 楼答案
我没有答案,但我能够确认这一点,并将片段简化为以下内容:
这将创建
OuterClass$1.class
这里是
javap -c
的OuterClass.class
:对于
OuterClass$PrivateInnerClass
如您所见,合成的构造函数采用
OuterClass$1
参数因此
javac
创建默认构造函数以获取额外的参数,类型为$1
,该默认参数的值为5: aconst_null
我发现
$1
如果以下任一项为真,则不会被创建:public class PrivateInnerClass
PrivateInnerClass
声明一个空构造函数new
static
等)李>可能相关