如果B扩展A,则无法转换列表<a> to List<b> (makes sense), but then why can one cast List<!--? extends A--> to List<b>?

时间:2018-03-08 23:34:16

标签: java generics casting

If a class B extends class A, one cannot cast List<A> to List<B> (cast 1 below). This makes sense, because if it were allowed, then one could read a B from the list even if it contained none.

However, in the code below, cast 2 from List<? extends A> to List<B> causes a warning. Shouldn't it generate an error for the same reason as before? In the code, the list only contains one object that is an A but not a B, and yet it is in a list deemed List<B>.

package test;

import java.util.LinkedList;
import java.util.List;

public class TypeLowerBoundCasting {

    static class A {}
    static class B extends A {}

    static void method1() {
        List<A> listOfAs = new LinkedList<A>();
        listOfAs.add(new A());
        // List<B> listOfAsAsListOfBs = (List<B>) listOfAs ; // cast 1: compiler error
        // B b = listOfAsAsListOfBs.get(0); // that would be bad
    }

    static void method2() {
        LinkedList<A> listOfAs = new LinkedList<A>();
        listOfAs.add(new A());
        List<? extends A> listOfAExtensions = listOfAs;
        List<B> listOfAsAsListOfBs = (List<B>) listOfAExtensions; // cast 2: warning, but compiles
        B b = listOfAsAsListOfBs.get(0); // that IS bad; causes a run-time error.
    }

    public static void main(String[] args) {
        method2();
    }
}

1 个答案:

答案 0 :(得分:3)

List<? extends A> 可能List<B>,因此您可以投射:

List<? extends A> list = new ArrayList<B>(); // lose type information
List<B> result = (List<B>) list; // regain type information

与您的行为类似:

Object o = "Hello World!"; // lose type information
String s = (String) o; // regain type information

不幸的是,第一次演员阵容未经检查。但正如你所看到的那样,那个地方的演员阵容仍然是一个有效的选择。

List<A>实际上永远不会是List<B>(除非您滥用原始类型),因为List<A>无法从List<B>分配(即List<B> }没有&#39;延伸&#39; List<A>)所以你不能施展:

List<A> list = new ArrayList<B>(); // Only works with: (List<A>) (List) new ArrayList<B>();