有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java:为什么可以对通配符集合进行强制转换?

假设我们有一个类a和一个从类a继承的类B。 假设我们有:

Set<A> setOfAs = new HashSet<>();

以下铸件:

((Set<B>) setOfAs)

将给我们运行时错误

但是,如果我们使用通配符并定义以下集合:

Set<? extends A> setOfAs = new HashSet<>();

我们在铸造方面没有问题:

((Set<B>) setOfAs)

为什么允许强制转换通配符集合,而禁止强制转换“常规”类型的集合


共 (2) 个答案

  1. # 1 楼答案

    we have no problem to do the casting:

    你会有一个未经检查的演员阵容警告,所以你并不是真的没有问题;只是编译器不能证明它肯定是错的,也不能在字节码中放入任何东西来捕捉它在运行时出错的事实

    ASet<? extends T>是一个Set,可以假设所有成员都可以安全地被转换到T而不需要ClassCastException

    ASet<? super T>将是一个Set,在其中添加AT是安全的,而不会在依赖于Set中元素类型的地方造成ClassCastException(我认为正确的技术术语是而不会造成堆污染

    A Set<T>是这两种有界类型的交集:可以向其中添加T的实例,其中的所有元素都是T的实例

    根据这些定义,Set<B>可以充当Set<? extends A>,因为任何可以转换为B的东西也可以转换为A

    但是,Set<A>不能充当Set<B>,因为它可能包含A的实例,而这些实例不是B的实例

  2. # 2 楼答案

    选角的整个想法就是说“我知道的比你多,编译器!”当物体的实际类型存在一些不确定性时

    在第二种情况下,这完全有道理。编译器知道setOfAsSet<? extends A>类型,这意味着“未知类型的Set,而未知类型扩展了A”。关于它可能是什么类型的HashSet存在不确定性。就编译器而言,可能是HashSet<B>

    Set<? extends A> setOfAs = new HashSet<A>();
    

    但它也可能是^{

    Set<? extends A> setOfAs = new HashSet<B>();
    

    你,通过施法,说“不,setOfAsaHashSet<B>”。编译器会说,“嗯,可能是这样,所以我相信你。”。你的额外知识是否真的正确,是另一回事

    然而,在第一种情况下,setofAs是类型HashSet<A>。由于类型为HashSet<A>的变量可以从不存储类型为HashSet<B>的对象,即它不会编译:

    Set<A> setOfAs = new HashSet<B>();
    

    关于Set的泛型参数没有不确定性。一定是A。你试图转换到HashSet<B>,只会导致编译器说“不,它永远不会是那样的!”