我的所有枚举扩展实现了一个接口,并有一个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);
}
}
答案 0 :(得分:1)
由于erasure,T
的特定类型在运行时尚未知晓。标准解决方案是将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
。