在下面的代码中:
class EnclosingClass
{
public static class BiNode extends Sub.IBiLink { }
private static class Sub
{
private static class IBiLink
{
}
}
}
在与其他.class文件一起编译时,我还看到一个名为“EnclosingClass $ 1.class”的文件。为什么这是自动创建的?怎么回事?
答案 0 :(得分:3)
首先看一下JVM规范中的类访问和propery修饰符表。
注意ACC_SYNTHETIC
标志,该解释指定它在源代码中不存在(简单来说,它将在编译器生成类时添加)。
让我们看一下EnclosingClass$1.class
的字节码(请注意,我只会粘贴重要的部分)。
javap -v EnclosingClass$1.class
产生以下结果
Classfile /C:/Users/jfrancoiss/Desktop/Nouveau dossier/EnclosingClass$1.class
Last modified 2015-03-31; size 190 bytes
MD5 checksum 5875440f1e7f5ea9a519d02fbec6dc8f
Compiled from "EnclosingClass.java"
class EnclosingClass$1
minor version: 0
major version: 52
flags: ACC_SUPER, ACC_SYNTHETIC
请注意,该类的访问标志包含ACC_SYNTHETIC
。
ACC_SYNTHETIC标志表示此类或接口是 由编译器生成,不会出现在源代码中。
确保生成的类是合成的另一个选项是编译为
javac -XD-printflat EnclosingClass.java
会产生
/*synthetic*/ class EnclosingClass$1 {
}
很好,但为什么要生成合成类?
Java反射教程可以帮助我们理解这一点。查看SyntheticConstructor
类
public class SyntheticConstructor {
private SyntheticConstructor() {}
class Inner {
// Compiler will generate a synthetic constructor since
// SyntheticConstructor() is private.
Inner() { new SyntheticConstructor(); }
}
}
因此,根据评论,合成类EnclosingClass$1.class
的创建是因为IBiLink
是私有的。
此时java reflection tutorial再次指定
由于内部类的构造函数引用了私有构造函数 对于封闭类,编译器必须生成一个包私有 构造函数。
在我们的例子中,我们没有明确地看到任何构造函数调用,但我们有这一行
public static class BiNode extends Sub.IBiLink { }
让我们尝试编译这段代码,看看会发生什么
class EnclosingClass
{
//public static class BiNode extends Sub.IBiLink { }
private static class Sub
{
private static class IBiLink
{
}
}
}
未生成EnclosingClass$1.class
。
调试时注意到更多细节
更改
private static class IBiLink
到
protected static class IBiLink
请注意,在编译时,不会创建EnclosingClass$1.class
。
为什么保护类没有生成合成类?
仅仅因为在保护课程时,你会隐含地访问每个超级课程。
为什么eclipse编译器不生成合成类?
Eclipse使用它内置的编译器,您可以配置它的严重性级别。
默认情况下,对封闭类型的不可访问成员的访问权限设置为忽略,如此图片所示。
将其更改为警告,您将收到以下消息。
让我相信eclipse,altought不会创建另一个类,会模仿它来模拟合成成员。