繁体   English   中英

使用通配符转换通用 class 的 Class 实例

[英]Casting Class instance of an generic class using wildcards

我目前真的无法理解这里发生的事情。 我有以下(最小)代码:

public class SillyCast {

    interface B {}
    interface D<T extends B> {}
    class C<T extends D<?>> {}
    class A<T extends B> extends C<D<T>> {}
    List<Class<? extends C<?>>> list = new ArrayList<>();

    void m() {
        list.add((Class<? extends C<?>>) A.class);
    }
}

在 Eclipse 中编译(和运行)此代码时,一切都按预期工作,但是从命令行(Oracle JDK)执行此操作时,在编译过程中出现以下错误:

error: incompatible types: Class<A> cannot be converted to Class<? extends C<?>> list.add((Class<? extends C<?>>) A.class);

我知道 Oracle JDK 的行为并不总是与 Eclipse JDT 完全相同,但这似乎很奇怪。

如何将A.class的实例添加到我的 ArrayList 中? 直觉上,这似乎应该是可能的。

为什么 Oracle JDK 和 Eclipse JDT 对这个演员表有不同的看法? 为什么 Oracle JDK 在执行此转换时遇到问题。

起初我认为这可能是一个错误,但我在不同的 Java 版本(8 和 11)上对此进行了测试,并且问题发生在所有版本上。 此外,这种演员阵容似乎太“简单”了,因为 go 可能在多个版本中都没有被注意到,所以希望设计上会这样。

不确定您要达到的目标,但这可以正常工作:

public class Main{
    static interface B {}
    static interface D<T extends B> {}
    static class C<T extends D<?>> {}
    static class A<T extends B> extends C<D<T>>{}

    static List<Class<? extends C>> list = new ArrayList<>();
    public static void main(String[] args) {
        list.add(A.class);
        list.add(C.class);
    }
}

这真的很令人困惑,你想达到什么目的? 您正在通过扩展其他接口的接口进行参数化(然后通过扩展由接口扩展接口参数化的类的类)。 这种复杂程度表明它可能需要一种不同的、更简单的方法:D

我认为正如@ferrouskid 指出的那样,这不起作用的原因可能是,尽管通常认为 C 不是 C> 的超级类型。

虽然这更像是一种混淆策略而不是真正的解决方案,但我目前的工作是通过在转换之前将A.class分配给变量来分散 Oracle 编译器的注意力(可能需要@SuppressWarnings("unchecked")

Class<?> aa = A.class;
list.add((Class<? extends C<?>>) aa);

免责声明:这种操作非常危险,因为强制转换可能在运行时失败。 因此,仅当您对受影响的方法具有完整的测试覆盖率时才这样做。

暂无
暂无

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

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