如何根据构造函数值获取枚举实例,并进行一般转换?

时间:2016-03-06 08:10:32

标签: java generics enums

我的所有枚举扩展实现了一个接口,并有一个arg构造函数/ displayValue:

public enum TCType implements CustomEnum{
    Hospital("Hospital"),
    AmbulatoryCenter("Ambulatory Center"),
    IndependentLaboratory("Independent Lab");

    private final String displayValue;
    private TCType(String value) {
        displayValue = value;
    }

    @Override
    public String getDisplayValue() {
        return displayValue;
    }
}

这是界面: 我也有一个默认方法find():输入:“Ambulatory Center”返回:TCType.AmbulatoryCenter

public interface CustomEnum{
    default String getDisplayValue(){
        return name();
    }
    String name();
}

如何在valueObj中获取TCType.AmbulatoryCenter?

代码:使用反射的通用setter方法 - 应该适用于任何实现CustomEnum的枚举

if (columnMethod.columnType.isEnum()) {// here columnMethod.columnType is TCType.
    String strVal = resultSet.getString(columnName); // strVal = "Ambulatory Center"
    if (strVal != null) {
    // I expect valueObj should be TCType.AmbulatoryCenter , however I get IllegalArugmentException
    valueObj = Enum.valueOf((Class<Enum>) columnMethod.columnType, strVal);
        columnMethod.method.invoke(obj, valueObj);

    }
}

编辑: 谢谢yshavit

我将find方法移动到enum util。

class EnumUtil {

    static CustomEnum find(String enumTypeClassName, String enumDisplayValue){
        try{
            Class clazz = Class.forName(enumTypeClassName);//"constants.AccountType"
            return find(clazz, enumDisplayValue);
        }catch(Exception e){
            throw new CoraException("Error casting ModelConstant type:" + enumTypeClassName + ", dispVal="+enumDisplayValue, e);
        }

    }
    static <T extends Enum & CustomEnum> CustomEnum find(Class<T> clazz, String enumDisplayValue) {
        for (T elem : clazz.getEnumConstants()) {
            if (elem.getDisplayValue().equals(enumDisplayValue)) {
                return (CustomEnum)elem;
            }
        }
        throw new NoSuchElementException("class="+clazz.getCanonicalName()+ ",displayVal=" +enumDisplayValue);
    }
}

因此客户端代码变为:

if (columnMethod.columnType.isEnum() &&  CustomEnum.class.isAssignableFrom(columnMethod.columnType)) {

            String s = resultSet.getString(columnName);
            if (s != null) {
                Object enumVal = EnumUtil.find(columnMethod.columnType.getTypeName(), s);
                columnMethod.method.invoke(obj,enumVal);
            }
        }

2 个答案:

答案 0 :(得分:1)

由于erasureT的特定类型在运行时尚未知晓。标准解决方案是将Class<T>的实例传递给find方法,或传递给CustomEnums构造函数(如果它是类)。如果我们做前者,它就是这样的:

T find(String name, Class<T> clazz) {
    for (T elem : clazz.getEnumConstants()) {
        if (elem.name().equals(name)) {
            return elem;
        }
    }
    throw new NoSuchElementException(name); // or whatever
}

在Java 8中,您可以进一步缩短它:

T find(String name, Class<T> clazz) {
    return Stream.of(clazz.getEnumConstants())
        .filter(name::equals)) // note, will NPE if name == null
        .findFirst()
        .get();
}

答案 1 :(得分:0)

Enum.valueOf的字符串参数是枚举的声明名称。您将通过描述:“Ambulatory Center”而不是“AmbulatoryCenter”。

您需要使用find方法代替valueOf

相关问题