关于使用通配符泛型转换对象的概念问题

Conceptual question about casting objects using wildcard generics

我试图理解为什么编译器对待内联声明的对象(使用通配符泛型)与首先将对象设置为变量的方式不同。

参见以下示例:

public class SillyTest{

    interface A<T extends B> {}
    interface B {}

    @Test
    public void m() {

        Class<?> b1 = A.class.getClass();
        Class<? extends B> bb1 = (Class<? extends B>) b1; // works fine

        Class<? extends B> bb2 = (Class<? extends B>) A.class.getClass(); // doesn't compile
        Class<? extends B> bb3 = (Class<? extends B>)(A.class.getClass()); // also doesn't compile
    }
}

注意:根据您的编译器配置,您可能需要添加 @SuppressWarnings("unchecked") 注释。

为什么编译器对这两种情况的处理不同?我希望由于编译器内联这些调用应该是等价的。除了这是一个未经检查的演员表(可能有效也可能无效)getClass() returns 和 Class<?>,所以我看不出应该以不同方式处理的原因。

因为 Class<A> 没有扩展 B,你的最后两个陈述显然是错误的,这可以在编译时确定。另一方面,b1Class<?> 类型,因此在编译时不知道 ? 是否扩展 B。需要进行运行时检查。