В Oracle JDK (пробовал с JDK 10.0.1) класс Class
имеет поле enumConstantDirectory
. Это поле имеет тип Map<String, T>
для Class<T>
. Он хранит константы перечисления T
по их именам. После инициализации класса enum enumConstantDirectory
все еще пуст. При первом вызове Enum.valueOf(Class<T> enumType, String name)
все константы данного перечисления T
сохраняются в enumConstantDirectory
.
Поскольку каждый класс enum уже имеет свое собственное отображение, мы можем попытаться использовать его вместо создания дополнительного локального отображения для / some / every enum / s.
Сначала я реализовал служебный класс:
public class Enums {
private static final Field DIRECTORY_FIELD;
static {
try {
DIRECTORY_FIELD = Class.class.getDeclaredField("enumConstantDirectory");
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
public static <T extends Enum<T>> T valueOfOrDefault(Class<T> enumType, String name, T defaultValue) throws Exception {
return getEnumConstantDirectory(enumType).getOrDefault(name, defaultValue);
}
public static <T extends Enum<T>> boolean hasValueFor(Class<T> enumType, String name) throws Exception {
Map<String, T> enumConstantDirectory = getEnumConstantDirectory(enumType);
return enumConstantDirectory.containsKey(name);
}
private static <T extends Enum<T>> Map<String, T> getEnumConstantDirectory(Class<T> enumType) throws Exception {
try {
DIRECTORY_FIELD.setAccessible(true);
Map<String, T> enumConstantDirectory = (Map<String, T>) DIRECTORY_FIELD.get(enumType);
return enumConstantDirectory;
}
finally {
DIRECTORY_FIELD.setAccessible(false);
}
}
}
Может использоваться следующим образом:
public enum Note {
DO, RE, MI, FA, SOL, LA, SI;
static {
Enum.valueOf(Note.class, Note.DO.name());
}
public static Note valueOfOrDefault(String name, Note defaultValue) throws Exception {
return Enums.valueOfOrDefault(Note.class, name, defaultValue);
}
public static <T extends Enum<T>> boolean hasValueFor(String name) throws Exception {
return Enums.hasValueFor(Note.class, name);
}
}
Подведем итог:
Как правило, можно проверить, представляет ли имя константу перечисления без дополнительных отображений или итерации по константам перечисления. Но, как всегда, с отражениями есть известные недостатки. Кроме того, необходимо убедиться, что константы перечисления хранятся в его классе.