smi*_*aiw 2 java reflection enums jvm-bytecode
Java 反射 API 包含一个方法Class.getEnumConstants(),可以确定一个类是否是一个enum类(null如果它认为该类不是一个enum,则返回),以及它的常量是什么。
我正在开发一个直接生成 JVM 字节码的程序,并试图生成一个枚举类。因此,我需要知道 Java 如何从字节码中识别枚举类,这样getEnumConstants才能正常工作。显然,该类需要扩展Enum,但这显然是不够的(例如,对应于 的字节码public class Example extends Enum<Example> {}不会被识别为enum);类的 JVM 字节码还需要哪些其他功能,以便 Java 的反射 API 将其识别为 Java enum,并能够确定其枚举常量?
为了编译一个enum类型,你必须用ACC_ENUM类的访问标志中的标志来标记该类。
此外,对于每个常量,您必须创建一个相应的public static final字段,ACC_ENUM该字段也在字段的访问标志中标记。
然后,您需要一个类初始值设定项(一个void名为的无参数方法<clinit>)来创建实例并将它们分配给字段。
但这还不够。注意语言规范,它指定了两个隐式声明方法的存在。
Run Code Online (Sandbox Code Playgroud)/** * Returns an array containing the constants of this enum * type, in the order they're declared. This method may be * used to iterate over the constants as follows: * * for(E c : E.values()) * System.out.println(c); * * @return an array containing the constants of this enum * type, in the order they're declared */ public static E[] values(); /** * Returns the enum constant of this type with the specified * name. * The string must match exactly an identifier used to declare * an enum constant in this type. (Extraneous whitespace * characters are not permitted.) * * @return the enum constant with the specified name * @throws IllegalArgumentException if this enum type has no * constant with the specified name */ public static E valueOf(String name);
这是编译器的职责。字节码生成工具将它们的实现插入到特定的枚举类型中。请注意,尽管是编译器生成的,但不应将这两种方法标记为合成的。
该规范没有解决反射将如何收集其信息的问题。它可以遍历标记的字段并读取它们,以组装一个数组,或者它可以只调用values()特定类型的方法。因此,您不能省略任何这些工件,也不能values()仅通过委托来实现该方法Class.getEnumConstants()。