InnerClasses属性

时间:2015-05-15 21:41:44

标签: java class jvm

InnerClasses attribute说明

  

如果类的成员是类或接口,则为   constant_pool表(以及它的InnerClasses属性)必须引用   对每个这样的成员,即使该成员没有另外提及   班级。这些规则意味着嵌套的类或接口成员   将为每个封闭类和for提供InnerClasses信息   每个直接成员。

     

outer_class_info_index:

     

如果C 不是某个类的成员或接口(即,如果C a   顶级类或接口(JLS§7.6)或本地类(JLS§14.3)   或匿名类(JLS§15.9.5)),...

您可以从第二段注意到本地类或匿名类不被视为“成员”。这意味着第一段不适用于本地类或匿名类。但是当我编译这段代码时(试过eclipse编译器和javac):

package bc_data;

public class Pokus {

    public void metoda() {

        class Pokus_Lokalni {

        }

    }

}

javap -v Pokus.class

Classfile /home/jara/projects/bp/bc_data/src/bc_data/Pokus.class
  Last modified May 15, 2015; size 321 bytes
  MD5 checksum cf9cd7707c297e7ba43b8408a9ff6e2f
  Compiled from "Pokus.java"
public class bc_data.Pokus
  SourceFile: "Pokus.java"
  InnerClasses:
       #5= #4; //Pokus_Lokalni=class bc_data/Pokus$1Pokus_Lokalni
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER

您可以看到本地类Pokus_Lokalni包含在InnerClasses属性中,即使类Pokus未另外提及它,因此它被视为“成员”?或者为什么本地类Pokus_Lokalni包含在InnerClasses属性中?它是由规范强制执行的吗?

2 个答案:

答案 0 :(得分:2)

我的想法是:

  • 为了反思,包含在类文件中的成员类需要强制(因为例如Class.getDeclaredClasses)。
  • 对于本地和匿名课程来说情况并非如此,但即使没有强制规定,也没有理由无法存储它们。
  

您可以从第二段注意到本地班级或匿名班级不被视为"成员"。

是的,他们不是会员。但它们仍然是内部类,所以它们会正常显示在这里。

答案 1 :(得分:1)

看一下“classes []”部分的第一句话:

  

constant_pool表中的每个CONSTANT_Class_info条目(表示不是包成员的类或接口C)必须在classes数组中只有一个相应的条目。

这意味着除了顶级以外的所有类都必须包含在InnerClasses中。

现在outer_class_info_index部分:

  

如果C不是类或接口的成员(即,如果C是顶级类或接口(JLS§7.6)或本地类(JLS§14.3)或匿名类(JLS§) 15.9.5)),outer_class_info_index项的值必须为零。

     

否则,outer_class_info_index项的值必须是constant_pool表的有效索引,并且该索引处的条目必须是CONSTANT_Class_info(§4.4.1)结构,表示C是其成员的类或接口。

这意味着如果一个类是嵌套的(是另一个类的成员),那么outer_class_info_index必须指向封闭类的CONSTANT_Class_info,但是对于local / anonymous类,存在一个封闭方法而不是封闭类。

在您的情况下,Pokus类没有义务为Pokus_Lokalni提供InnerClasses条目。无论如何,看起来javac包含它,我想我知道为什么。

如果你有一个本地类,那么它可以在声明它的方法中使用,也可以根本不使用(让我们忽略用反射访问它的可能性)。未使用的本地课程似乎是一个非常奇怪和罕见的事情,所以它可能不值得努力以不同的方式对待这种情况。所以javac可能只是在常量池中添加所有本地类(因此在InnerClasses中)。