Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么编译一个包含静态嵌套类的类会创建一个名为";的新.class文件;随附类别$1“;?_Java_Javac_Nested Class_.class File - Fatal编程技术网

Java 为什么编译一个包含静态嵌套类的类会创建一个名为";的新.class文件;随附类别$1“;?

Java 为什么编译一个包含静态嵌套类的类会创建一个名为";的新.class文件;随附类别$1“;?,java,javac,nested-class,.class-file,Java,Javac,Nested Class,.class File,在以下代码中: class EnclosingClass { public static class BiNode extends Sub.IBiLink { } private static class Sub { private static class IBiLink { } } } 在与其他.class文件一起编译时,我还看到一个名为“EnclosingClass$1.class”

在以下代码中:

 class EnclosingClass
 { 
     public static class BiNode extends Sub.IBiLink { }
     private static class Sub
     {
         private static class IBiLink
         {  
         } 
     }
}

在与其他.class文件一起编译时,我还看到一个名为“EnclosingClass$1.class”的文件。为什么会自动创建这个文件?发生了什么?

首先查看JVM规范中的类访问和属性修饰符表

请注意
ACC\u SYNTHETIC
标志,该标志指定源代码中不存在它(简单地说,它将在编译器生成类时添加)


让我们看一下
封闭类$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\u SYNTHETIC

ACC_合成标志表示该类或接口已 由编译器生成,不出现在源代码中

确保生成的类是合成类的另一个选项是编译为

javac -XD-printflat EnclosingClass.java
那会产生什么

/*synthetic*/ class EnclosingClass$1 {
}

很好,但是为什么要生成一个合成类呢

Java反射教程可以帮助我们理解这一点。看一下课堂上的评论

因此,根据注释,创建了包含$1.class的合成类
是因为
IBiLink
是私有的

再一次,在这一点上指定

因为内部类的构造函数引用私有构造函数 对于封闭类,编译器必须生成私有包 构造器

在我们的例子中,我们没有明确看到任何构造函数调用,但我们有这一行

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。已生成类


调试时注意到的更多详细信息

改变

private static class IBiLink

请注意,编译时,不会创建
封闭类$1.class

为什么保护类不会生成合成类

这仅仅是因为在保护类时,您可以隐式地访问每个超类


为什么eclipse编译器不生成合成类?

Eclipse使用它的内置编译器,您可以配置它的严重性级别

默认情况下,对封闭类型的不可访问成员的访问设置为忽略,如您在此图像上所示

例如,将其更改为“警告”,您将收到以下消息


这让我相信eclipse不会创建其他类,而是会模拟它来模拟合成成员。

这里定义的所有内部类都是静态的,eclipse编译器不会生成这样的类文件<代码>JavaC1.8.0_20。根据规范afaik,不需要这样的.class文件。这可能会使javac变得更容易。当
IBiLink
声明为包本地时,不会生成包含$1的
包,尽管我不明白为什么。您描述的类签名是用于匿名内部类的。@vsnyc Nice find。第二个(也是投票最高的)答案更令人满意,因为Oak似乎有一个似是而非的答案。
class EnclosingClass
 { 
     //public static class BiNode extends Sub.IBiLink { }
     private static class Sub
     {
         private static class IBiLink
         {  
         } 
     }
}
private static class IBiLink
protected static class IBiLink