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);