问题描述:

Suppose you have a text file like:

my_setting = ON

some_method = METHOD_A

verbosity = DEBUG

...

That you wish to to update a corresponding object accordingly:

Setting my_setting = ON;

Method some_method = METHOD_A;

Verbosity verbosity = DEBUG;

...

Where all are different kind of enums.

I would like to have a generic way to instantiate the enum values. That is, at runtime using reflection, and without knowing the enum types of the object in advance.

I would have imagined something like this:

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 //...

}

The question is: what should there be instead? Is it even possible to instantiate an unknown enum given its String representation?

网友答案:
field.set(this, Enum.valueOf((Class<Enum>) field.getType(), value));
  • getClass() after getType() should not be called - it returns the class of a Class instance
  • You can cast Class<Enum>, to avoid generic problems, because you already know that the Class is an enum
网友答案:

You have an extra getClass call, and you have to cast (more specific cast per Bozho):

field.set(test, Enum.valueOf((Class<Enum>) field.getType(), value));
网友答案:

Alternative solution with no casting

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
}
网友答案:

You may code your Enum similar tho this:

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

Then you may easily create Enum from String without reflection:

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

This solution is not originated from myself. I read it from somewhere else, but I can't recall the source.

相关阅读:
Top