考虑我有一个界面com.mycompany.SomeInterface
和一个枚举com.mycompany.SomeEnum implements SomeInterface
。我希望在运行时使用Reflection API获取此类的所有枚举常量 - 作为SomeInterface
的实例。
目前,我的代码(在类EnumConstantGetter
中)是这样的:
Class<?> clazz = EnumConstantGetter.class.getClassLoader().
loadClass("com.mycompany.SomeEnum");
if (!(SomeInterface.class.isAssignableFrom(clazz)) {
throw new Exception("the class doesn't implement SomeInterface");
}
if (!(clazz.isEnum()) {
throw new Exception("not an enum");
}
Class<? extends Enum<? extends SomeInterface>> castClass =
(Class<? extends Enum<? extends SomeInterface>>) clazz; // cast #1
ArrayList<SomeInterface> vals = new ArrayList<SomeInterface>();
for (Enum<? extends SomeInterface> enumConstant :
castClass.getEnumConstants()) {
vals.add((SomeInterface) enumConstant); // cast #2
}
上面的代码似乎有效,但我在创建castClass
时收到编译器警告。
我的问题是:代码中注明的两个强制转换(类上的强制转换和常量上的强制转换)是否必须基于我的检查有效?
换句话说,Enum<? extends T>
的每个成员是否都保证实施T
?
如果答案是“是的,演员阵容是安全的”,那么为什么编译器会给我这个警告?
如果没有,为什么不呢?或者,在什么情况下例程会失败?
编辑:由于我上面的代码显然令人困惑,所以我的解释是所谓的正在发生的事情:
SomeEnum
中加载名为com.mycompany
的类,并将其Class
对象存储在变量中。SomeInterface
接口。SomeInterface
的枚举,将其投放到Class<? extends Enum<? extends SomeInterface>>
- 强制转换#1 SomeInterface
- 强制转换#2 - 并将其添加到常量列表中。谢谢!
答案 0 :(得分:5)
您可以执行以下操作:
Class<?> clazz = ...;
Class<? extends SomeInterface> someInterfaceClass;
try {
someInterfaceClass = clazz.asSubclass(SomeInterface.class);
}
catch (ClassCastException cce) {
throw new IllegalStateException("Specified type doesn't implement SomeInterface", cce);
}
SomeInterface[] enumConstants = someInterfaceClass.getEnumConstants();
if (enumConstants == null) {
throw new IllegalStateException("Specified type is not an enum.");
}
//use constants
这可以避免警告,因为asSubclass
已被选中,如果null
对象“不代表枚举类型,则getEnumConstants
会返回Class
。