为啥编译包含静态嵌套类的类会创建一个名为“EnclosureClass$1”的新 .class 文件? [复制]
Posted
技术标签:
【中文标题】为啥编译包含静态嵌套类的类会创建一个名为“EnclosureClass$1”的新 .class 文件? [复制]【英文标题】:Why does compiling a class containing static nested classes create a new .class file named "EnclosingClass$1"? [duplicate]为什么编译包含静态嵌套类的类会创建一个名为“EnclosureClass$1”的新 .class 文件? [复制] 【发布时间】:2015-03-25 18:49:34 【问题描述】:在下面的代码中:
class EnclosingClass
public static class BiNode extends Sub.IBiLink
private static class Sub
private static class IBiLink
在与其他 .class 文件一起编译时,我还看到一个名为“EnclosureClass$1.class”的文件。为什么会自动创建它?怎么回事?
【问题讨论】:
这里定义的所有内部类都是静态的 Eclipse 编译器不会生成这样的类文件。javac 1.8.0_20
确实如此。根据规范 afaik,不需要这样的 .class 文件。它可能会使 javac 的事情变得更容易。
当IBiLink
被声明为包本地时,不会生成Enclosing$1
,虽然我不明白为什么。
你描述的类签名是一个匿名内部类。
@vsnyc 不错的发现。该线程中的第二个(也是投票最高的)答案更加令人满意,因为 Oak 似乎有一个合理的答案。 ***.com/a/2883541/312407
【参考方案1】:
首先看一下 JVM 规范中的类访问和属性修饰符表。
注意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
类中的 cmets
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 使用它内置的编译器,你可以配置它的严重级别。
默认情况下,对封闭类型的不可访问成员的访问权限设置为 ignore,正如您在这张图片中看到的那样。
例如将其更改为警告,您将收到以下消息。
这让我相信 eclipse,虽然不会创建其他类,但会模仿它来模拟合成成员。
【讨论】:
以上是关于为啥编译包含静态嵌套类的类会创建一个名为“EnclosureClass$1”的新 .class 文件? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
为啥会创建一个名为 Azure Blob 存储容器内文件夹名称的空文件?