Class.as具有多个有界类型和未检查强制转换的子类



我有一个用类型<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);
    }
}
//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。您只验证了边界。假设我们有T1T2:

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);
}

这是因为,如果没有类型参数,在极少数情况下,您可以真正利用同时是enumRunnable的知识。如果创建类的实例,则需要将其分配给类型为RunnableEnum的变量/字段;你不能两者都做。

我相信你根本不能。。。在我看来,最好的解决方案是直接传递Class<T> clazz作为参数,而不是它的String name

最新更新