我发现了另一种变体,它既不需要迭代所有枚举常量,也不需要抛出异常...但它是实现特定的,即使用未记录的方法。 它适用于Sun的JDK 1.6.0_20(并且是通过阅读来自1.6.0_13的源代码制作的)。
public static <E extends Enum<E>> boolean enumTypeContains(Class<E> e, String s) {
try {
Method enumDir = Class.class.getDeclaredMethod("enumConstantDirectory");
enumDir.setAccessible(true);
Map<?,?> dir = (Map<?,?>)enumDir.invoke(e);
return dir.containsKey(s);
}
catch(NoSuchMethodException ex) {
throw new Error(ex);
}
catch(IllegalAccessException ex) {
throw new Error(ex);
}
catch(InvocationTargetException ex) {
throw new Error(ex.getCause());
}
}
如果我们在
java.lang
包中,代码可能看起来像这样:
public static <E extends Enum<E>> boolean enumTypeContains(Class<E> e, String s) {
return e.enumConstantDirectory().containsKey(s);
}
这里使用了 Class.enumConstantDirectory()
方法,它会在第一次调用时创建一个包含所有枚举常量的映射表,其中键为枚举常量的名称,值为枚举常量本身。(我们也可以手动创建这样的映射表。)
这个方法被 Enum.valueOf(Class, String)
内部使用,据说也被 EnumType.valueOf(String)
使用(取决于编译器)。
在第一次调用 enumConstantDirectory
或 getEnumConstants()
时,一个私有的辅助方法会调用 EnumType.values()
(由编译器实现)。然后将结果重复使用于这两个方法的后续调用。