我有一个类型为<T extends Enum<T> & Runnable>
的类。我有一个成员变量Class<T> bar
,我按类名设置t = (Class<T>) Class.forName(name)
。这给了我一个未经检查的投射警告。
通常情况下,使用asSubclass可以在类似的情况下使用,但由于T
有多个边界,我无法在没有编译器警告的情况下使用它:
//This is type safe, but I still get an unchecked cast warning
t = (Class<T>) Class.forName(className).asSubclass(Enum.class).asSubclass(Runnable.class);
我可以在不使用@SupressedWarning("unchecked")
的情况下以任何方式摆脱此警告吗?
完整示例:
public class Example<T extends Enum<T> & Runnable> {
Class<T> t;
Example(String className) throws ClassNotFoundException {
t = (Class<T>) Class.forName(className).asSubclass(Enum.class).asSubclass(Runnable.class);
}
}
答案 0 :(得分:4)
//This is type safe, but I still get an unchecked cast warning
t = (Class<T>) Class.forName(className).asSubclass(Enum.class).asSubclass(Runnable.class);
哇,慢下来一秒!这是真的吗?不,这不对!您所做的就是确定与传入名称匹配的类是Runnable
和Enum
,而不是它实际上是T
。您只验证了边界。想象一下,我们有课程T1
和T2
:
package foo;
public enum T1 implements Runnable {
;
@Override
public void run() {
}
}
package foo;
public enum T2 implements Runnable {
;
@Override
public void run() {
}
}
然后这很好用,但显然不是类型安全的:
Example<T1> example = new Example<T1>("foo.T2");
Class<T1> t1Clazz = example.t; //uh oh...
这也不是多重边界的问题。只有一个绑定你就会遇到同样的问题。
正如@ sp00m提到的那样,真正的解决方案可能就是传递Class<T>
。
另一方面,如果T
只需要内部(即指定多个边界)并且不需要实际暴露,那么另一个选择是将类保持在两个单独的参考。例如:
Class<? extends Runnable> runnableClass;
Class<? extends Enum> enumClass;
Example(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Class<?> clazz = Class.forName(className);
runnableClass = clazz.asSubclass(Runnable.class);
enumClass = clazz.asSubclass(Enum.class);
}
这是因为,如果没有类型参数,在极少数情况下您可以实际获取知识的优势同时enum
和Runnable
时间。如果您创建了类的实例,则需要将其分配给类型为Runnable
或Enum
的变量/字段;你不能两者兼顾。
答案 1 :(得分:1)
我相信你根本不能......我认为最好的解决方案是直接将Class<T> clazz
作为参数传递而不是String name
。