Jas*_*n S 8 java reflection enums
这与Java类似但不完全相同:使用反射实例化枚举
我有一个Map<Enum<?>, FooHandler>我想用来映射Enums(我不关心哪种类型,或者即使它们是同一类型,只要它们是枚举常量)到我的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);
}
Run Code Online (Sandbox Code Playgroud)
警告#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
}
Run Code Online (Sandbox Code Playgroud)
警告:
- 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<?>
Run Code Online (Sandbox Code Playgroud)错误:
- 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>>
Run Code Online (Sandbox Code Playgroud)还有这个:
static private Enum<?> getEnum(String enumFullName) {
...
Class<Enum<?>> cl = (Class<Enum<?>>)Class.forName(enumClassName);
// 1
return Enum.valueOf(cl, enumName);
// 2
Run Code Online (Sandbox Code Playgroud)
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>>对于#1,没有解决办法,除了SuppressWarnings("unchecked").
对于#2,声明存在问题:
static private <E extends Enum<E>> E getEnum(String enumFullName)
Run Code Online (Sandbox Code Playgroud)
您可以返回E,但编译器无法确定E.没有任何类型E或类型的论据Class<E>,这将允许它.你可以写它,但在某个地方会有一个未经检查的演员,当你打电话给它时,你可能会得到一个ClassCastException.所以不要这样做.
只需将其更改为
static private Enum<?> getEnum(String enumFullName)
Run Code Online (Sandbox Code Playgroud)
因为这会起作用并且更公平.您将在每个呼叫站点上收到警告,这是正确的,因为有一些警告.
签名
static private <E extends Enum<E>> getEnum(String enumFullName)
Run Code Online (Sandbox Code Playgroud)
这对你没有好处.
该<E extends Enum<E>>允许方法的调用分配的结果getEnum对任何enum他们想要的,没有任何铸造类型:
SomeEnum e = getEnum("com.foo.SomeOtherEnum.SOMETHING"); // ClassCastException!
Run Code Online (Sandbox Code Playgroud)
然而,这没有任何意义......如果调用者知道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;
}
Run Code Online (Sandbox Code Playgroud)
以上编译没有警告并正常工作.演员以Class<Enum>警告被抑制,因为我们知道它是不是安全做到这一点,那Enum.valueOf将炸毁,如果给定名字的类不是一个enum类,这就是我们想要做的.