java在映射中使用通用枚举类
我有一个类名称到它们的枚举类的映射,我有一个方法,可以将像"SomeEnum.FIRST"
这样的字符串解析到实际的对象中。但是Enum.valueOf
不接受Class<? extends Enum<?>>
,而映射不能存储Class<T extends Enum<T>>
对于代码,映射如下所示:
private static final HashMap<String, Class<? extends Enum<?>>> enumsMap;
static {
enumsMap = new HashMap<>();
// These are two DIFFERENT enum classes!
registerEnum(SomeEnum.class);
registerEnum(AnotherEnum.class);
}
private static void registerEnum(Class<? extends Enum<?>> enumClass) {
enumsMap.put(enumClass.getSimpleName(), enumClass);
}
下面是解析器(删除了不必要的代码):
public <T extends Enum<T>> Object[] parse(List<String> strParameters) {
Object[] parameters = new Object[strParameters.size()];
for (int i = 0; i < parameters.length; i++) {
String strParameter = strParameters.get(i);
int delim = strParameter.lastIndexOf('.');
String className = strParameter.substring(0, delim - 1);
String enumName = strParameter.substring(delim + 1);
Class<T> enumClass = (Class<T>) enumsMap.get(className);
parameters[i] = Enum.valueOf(enumClass, enumName);
}
return parameters;
}
现在如果我调用这个parse
,我的IDE(安卓studio)告诉我,“Unchecked method”parse(List)“invocation”,而且afaik这是因为这个泛型类型。如果我在parse
中删除它,它将不会编译,但警告将消失。有什么好办法吗
# 1 楼答案
没有安全的方法可以使映射值的泛型类型取决于相应的键
但是,您可以自己存储枚举常量:
我改变了什么:
enumsMap
现在是Map<String, Map<String, ?>>
。每个值都是由常量名称键入的枚举常量的映射?
就足够了;记住常量值是枚举没有好处,因为parse
返回Object[]
李>registerEnum
具有泛型类型,以保证其参数是有效的枚举类型。它不存储类参数,而是存储该枚举的常量李>parse
不需要泛型类型,因为它返回Object[]
李>parse
不使用任何Enum方法,因此泛型类型安全不再是一个问题李>strParameter.substring(0, delim);
而不是delim - 1
。您希望整个子字符串一直到但不包括句点李># 2 楼答案
如果您有如下枚举:
然后,您可以使用下面的代码实现您正在讨论的映射类型
不过,这并不能绕过未经检查的演员阵容;它只是暂时对你隐藏它。您可以看到
SuppressWarnings
用于隐藏关于enumType
的警告的位置。一般来说,最好在尽可能有限的范围内应用警告抑制。在本例中,它是针对单个任务的。虽然这通常可能是一个危险信号,但在本例中,我们知道映射中唯一的值实际上是枚举类,因为它们必须是由addEnum
添加的然后,它可以用作:
其中打印:
你会注意到我把
parseUnsafely
和parse
分成了不同的方法。我们不想直接公开parseUnsafely
的原因是它通过其返回类型提供了一个我们实际上无法强制执行的保证。如果它被公开了,那么我们可以编写如下代码可编译,但在运行时失败,并出现强制转换类异常