Java:使用reflection实例化枚举

假设你有一个文本文件,如:

my_setting = ON some_method = METHOD_A verbosity = DEBUG ... 

您希望相应地更新相应的对象:

 Setting my_setting = ON; Method some_method = METHOD_A; Verbosity verbosity = DEBUG; ... 

在哪里都是不同种类的枚举。

我想有一个通用的方式来实例化枚举值。 也就是说,在运行时使用reflection,而不用事先知道对象的枚举types。

我会想像这样的事情:

 for (ConfigLine line : lines) { String[] tokens = line.string.split("=", 2); String name = tokens[0].trim(); String value = tokens[1].trim(); try { Field field = this.getClass().getDeclaredField(name); if(field.getType().isEnum()) { // doesn't work (cannot convert String to enum) field.set(this, value); // invalid code (some strange generics issue) field.set(this, Enum.valueOf(field.getType().getClass(), value)); } else { /*...*/ } } catch //... } 

问题是:应该有什么呢? 是否有可能实例化一个未知的枚举给它的string表示?

 field.set(this, Enum.valueOf((Class<Enum>) field.getType(), value)); 
  • getType() getClass()之后的getClass()不应该被调用 – 它返回一个Class实例的Class
  • 您可以强制Class<Enum> ,以避免generics问题,因为您已经知道Class是一个enum

你有一个额外的getClass调用,你必须施放(每个Bozho更具体的施放):

 field.set(test, Enum.valueOf((Class<Enum>) field.getType(), value)); 

没有铸造的替代解决scheme

 try { Method valueOf = field.getType().getMethod("valueOf", String.class); Object value = valueOf.invoke(null, param); field.set(test, value); } catch ( ReflectiveOperationException e) { // handle error here } 

你可以编码你的枚举类似的这个:

 public enum Setting { ON("ON"),OFF("OFF"); private final String setting; private static final Map<String, Setting> stringToEnum = new ConcurrentHashMap<String, Setting>(); static { for (Setting set: values()){ stringToEnum.put(set.setting, set); } } private Setting(String setting) { this.setting = setting; } public String toString(){ return this.setting; } public static RequestStatus fromString(String setting){ return stringToEnum.get(setting); } } 

然后,你可以很容易地创build从string的枚举没有reflection:

 Setting my_settings = Setting.fromString("ON"); 

这个解决scheme不是来自我自己。 我从其他地方读了它,但我不记得来源。

接受的答案会导致警告,因为它使用原始typesEnum而不是Enum <T extends Enum <T >>。

为了解决这个问题,你需要使用这样一个通用的方法:

 @SuppressWarnings("unchecked") private <T extends Enum<T>> T createEnumInstance(String name, Type type) { return Enum.valueOf((Class<T>) type, name); } 

像这样调用它:

 Enum<?> enum = createEnumInstance(name, field.getType()); field.set(this, enum);