Я нашел другой вариант, который не должен ни перебирать все константы перечисления, ни выдавать исключение ... но это зависит от реализации, то есть использует недокументированные методы. Это работает для 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()
(который реализуется компилятором). Затем результат повторно используется для последующих вызовов этих двух методов.