这与Java: instantiating an enum using reflection
类似但不完全相同我有一个Map<Enum<?>, FooHandler>
我想用来映射Enum
(我不关心哪种类型,或者即使它们是相同的类型,只要它们是枚举常量)到我的FooHandler
班。
我想使用我阅读的文本文件填充此地图。我可以让它工作,但我有两个警告,我想绕过:
static private <E extends Enum<E>> E getEnum(String enumFullName) {
// see https://stackoverflow.com/questions/4545937/
String[] x = enumFullName.split("\\.(?=[^\\.]+$)");
if (x.length == 2)
{
String enumClassName = x[0];
String enumName = x[1];
try {
Class<E> cl = (Class<E>)Class.forName(enumClassName);
// #1
return Enum.valueOf(cl, enumName);
}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return null;
}
public void someMethod(String enumName, String fooHandlerName)
{
FooHandler fooHandler = getFooHandler(fooHandlerName);
Enum e = getEnum(enumName);
// #2
map.put(e, fooHandler);
}
警告#1:未经检查的演员 警告#2:枚举是一种原始类型。
我得到了#1并且可能只是发出警告我想,但我似乎无法击败警告#2;我试过Enum<?>
,这只是给我一个关于泛型类型捕获绑定不匹配的错误。
更糟糕的替代实施:
在我的<E extends Enum<E>>
泛型返回值之前,我尝试返回Enum并且它不起作用;我收到了这些警告/错误:
static private Enum<?> getEnum(String enumFullName) {
...
Class<?> cl = (Class<?>)Class.forName(enumClassName);
// 1
return Enum.valueOf(cl, enumName);
// 2
}
警告:
- Type safety: Unchecked cast from Class<capture#3-of ?> to Class<Enum>
- Enum is a raw type. References to generic type Enum<E> should be parameterized
- Enum is a raw type. References to generic type Enum<E> should be parameterized
- Unnecessary cast from Class<capture#3-of ?> to Class<?>
错误:
- Type mismatch: cannot convert from capture#5-of ? to Enum<?>
- Type safety: Unchecked invocation valueOf(Class<Enum>, String) of the generic method
valueOf(Class<T>, String) of type Enum
- Bound mismatch: The generic method valueOf(Class<T>, String) of type Enum<E> is not
applicable for the arguments (Class<capture#5-of ?>, String). The inferred type capture#5-of ? is not
a valid substitute for the bounded parameter <T extends Enum<T>>
和此:
static private Enum<?> getEnum(String enumFullName) {
...
Class<Enum<?>> cl = (Class<Enum<?>>)Class.forName(enumClassName);
// 1
return Enum.valueOf(cl, enumName);
// 2
Type safety: Unchecked cast from Class<capture#3-of ?> to Class<Enum<?>>
Bound mismatch: The generic method valueOf(Class<T>, String) of type Enum<E> is not applicable for the arguments (Class<Enum<?>>, String). The inferred type Enum<?> is not a valid substitute for the bounded parameter <T extends Enum<T>>
答案 0 :(得分:6)
对于#1,除了SuppressWarnings("unchecked")
之外没有解决方案。
对于#2,声明存在问题:
static private <E extends Enum<E>> E getEnum(String enumFullName)
您可以返回E
,但编译器无法确定E
。没有类型E
或Class<E>
或类似的论据,这将允许它。你可以写它,但在某个地方会有一个未经检查的演员,当你调用它时,你可能会得到一个ClassCastException
。所以不要这样做。
只需将其更改为
即可static private Enum<?> getEnum(String enumFullName)
因为这会起作用并且更公平。你会收到每个呼叫网站的警告,这是正确的,因为有警告的东西。
答案 1 :(得分:5)
签名
static private <E extends Enum<E>> getEnum(String enumFullName)
在这里没有任何好处。
<E extends Enum<E>>
允许方法的调用者将getEnum
的结果分配给他们想要的任何enum
类型而不进行任何转换:
SomeEnum e = getEnum("com.foo.SomeOtherEnum.SOMETHING"); // ClassCastException!
然而,这没有任何意义......如果调用者知道该方法将返回哪种特定类型的enum
,他们可以做一些比SomeEnum.valueOf("SOMETHING")
更明智的事情。
唯一有意义的是getEnum
只返回Enum<?>
,这似乎是你真正想做的事情:
static private Enum<?> getEnum(String enumFullName) {
String[] x = enumFullName.split("\\.(?=[^\\.]+$)");
if(x.length == 2) {
String enumClassName = x[0];
String enumName = x[1];
try {
@SuppressWarnings("unchecked")
Class<Enum> cl = (Class<Enum>) Class.forName(enumClassName);
return Enum.valueOf(cl, enumName);
}
catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
return null;
}
以上编译没有任何警告并正常工作。转换为Class<Enum>
警告被抑制,因为我们知道这样做是不安全的,如果具有给定名称的类不是Enum.valueOf
类,enum
将会爆炸这就是我们想要做的事情。