简体   繁体   English

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

[英]Class.asSubclass with multiple bounded types and unchecked cast

I have a class which is generified with the type <T extends Enum<T> & Runnable> . 我有一个类,其类型为<T extends Enum<T> & Runnable> I have a member variable Class<T> bar which I set by the class name: t = (Class<T>) Class.forName(name) . 我有一个成员变量Class<T> bar ,我按类名设置: t = (Class<T>) Class.forName(name) This gives me an unchecked cast warning. 这给了我一个未经检查的投射警告。

Normally, using asSubclass can be used in similar situations, but since T has multiple bounds, I'm not able to use it without getting a compiler warning: 通常,使用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);

Can I get rid of this warning in any way, without using @SupressedWarning("unchecked") ? 我可以在不使用@SupressedWarning("unchecked")情况下以任何方式摆脱此警告吗?

Full example: 完整示例:

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

Whoa, slow down a second! 哇,放慢一秒! Is that actually true? 这是真的吗? No it's not! 不,这不对! All you've done is establish that the class matching the passed-in name is both a Runnable and an Enum , not that it is actually T . 你所做的就是确定匹配传入名称的类是RunnableEnum ,而不是它实际上是T You've only validated the bounds. 您只验证了边界。 Imagine we had classes T1 and T2 : 想象一下,我们有T1T2类:

package foo;
public enum T1 implements Runnable {
    ;
    @Override
    public void run() {
    }
}

package foo;
public enum T2 implements Runnable {
    ;
    @Override
    public void run() {
    }
}

Then this works fine, but is obviously not type safe: 然后这很好,但显然不是类型安全的:

Example<T1> example = new Example<T1>("foo.T2");
Class<T1> t1Clazz = example.t; //uh oh...

This isn't a problem of multiple bounds either. 这也不是多重边界的问题。 You'd have the same problem with only one bound. 只有一个绑定你有同样的问题。

As @sp00m mentions, the real solution is probably to pass in Class<T> here. 正如@ sp00m所提到的,真正的解决方案可能是在这里传递Class<T>

Edit 编辑

If, on the other hand, T was only needed internally (ie to specify the multiple bounds) and need not actually be exposed, then another option is to maintain the class in two separate references. 另一方面,如果仅在内部需要T (即指定多个边界)并且不需要实际暴露,则另一个选项是将类维护在两个单独的引用中。 For example: 例如:

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

That's because, without the type parameter, there are very few circumstances where you could actually take advantage of the knowledge that it's an enum and a Runnable at the same time. 这是因为,如果没有类型参数,在极少数情况下您可以实际利用它同时具有enumRunnable的知识。 If you create an instance of the class, you need to assign it to a variable/field of type Runnable or Enum ; 如果创建类的实例,则需要将其分配给RunnableEnum类型的变量/字段; you can't do both. 你不能两者兼顾。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM