3

考虑一下我有一个 interfacecom.mycompany.SomeInterface和一个 enum com.mycompany.SomeEnum implements SomeInterfaceSomeInterface我想在运行时使用反射 API获取此类的所有枚举常量——作为实例。

目前,我的代码(在类中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吗?

如果答案是“是的,强制转换是安全的”,那么为什么编译器会给我这个警告呢?

如果不是,为什么不呢?或者,在什么情况下例程会失败?

编辑:由于我上面的代码显然令人困惑,这是我对应该发生的事情的解释:

  1. 加载SomeEnum包中命名的类com.mycompany并将其Class对象存储在变量中。
  2. 确保引用的类实现了SomeInterface接口。
  3. 确保引用的类是枚举。
  4. 正如我们所知,它是一个 enum 实现SomeInterface,将其转换为Class<? extends Enum<? extends SomeInterface>> - cast #1
  5. 循环遍历所有枚举常量。
  6. 对于每个常量,将其转换为SomeInterface - cast #2 -并将其添加到常量列表中。

谢谢!

4

1 回答 1

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,则会检查并getEnumConstants返回。nullClass

于 2012-11-21T00:52:12.510 回答