2 回答
对上一个答案的一些补充:
InnerClasses 属性是用于在包含类中存储包含的内部/嵌套类,还是在内部/嵌套类中用于引用“容器”类?
每个已编译类的字节码都存储在一个单独的 .class 文件中。实际的“内部类”不存储在该属性中。正如上一篇文章所指出的,该属性仅指向编译器在创建字节码时知道的类。
类文件中的 InnerClasses 属性是否足够?例如,内部/嵌套类是否必须遵循使用 $ 修饰的名称,或者这只是一个约定?
有没有办法在不设置 InnerClasses 属性的情况下使类看起来像 JVM 的内部/嵌套类,这是否取决于 JLM 供应商?(我记得听说 IBM 的实施在某些部分的要求不那么严格。)
对于这两个问题,我都不确定。但我认为内部/嵌套类的概念是 Java 语言(因此 Java 编译器提供)的东西。在字节码中,声明为普通公共类的类与某些嵌套类或内部类之间不应有任何区别。您可以轻松地尝试给定的虚拟机如何处理这个问题,如下所示:
- 创建一个包含一些嵌套类和内部类的类
- 编写一个小程序,尝试通过定义类范围之外的反射来加载和实例化其中一个内部类。您必须在此处使用反射,因为 Java 编译器不允许您实例化不在范围内的嵌套类!如果您可以成功实例化该类,则证明 VM 在内部不会以不同方式处理嵌套类和普通类。
JVM 的类加载机制与 Java 反射有多大的交互作用?是否有可能使 JVM 不同意 Java 反射的结果?
我不明白最后这个问题。当您说虚拟机和反射应该不同意时,您能否解释一下您的意思?
我知道类文件中有一个内部类属性,但这是否足够?
InnerClasses 属性位于字节码中,它列出了外部类的所有已知内部类。这不是您可以直接使用的东西。
例如,内部/嵌套类是否必须遵循使用 $ 修饰的名称,或者这只是一个约定?
编译器将遵循此约定,您无法控制它。
有没有办法在不设置内部类属性的情况下使类看起来像 JVM 的内部/嵌套类,这是否取决于 JLM 供应商?(我记得听说 IBM 的实施在某些部分的要求不那么严格。)
您可以创建一个具有相同名称的类。你可以自己试试。
JVM 的类加载机制与 Java 反射有多大的交互作用?
我不相信类加载器使用反射。然而,反射可能会从类加载器的同一个地方获取它的信息。我不明白为什么这很重要。
是否有可能使 JVM 不同意 Java 反射的结果?
您可以使用反射来破坏基于反射的对象中的数据。同样,不确定您为什么要这样做。