泛型,继承和子类型中所述,泛型类或泛型接口不仅仅因为它们的类型之间存在关系而相关。但是,您可以使用通配符在泛型类或泛型接口之间创建关系。
    给定以下两个常规(非泛型)类:

    1. class A { /* ... */ }
    2. class B extends A { /* ... */ }

    编写以下代码是合理的:

    1. B b = new B();
    2. A a = b;

    此示例显示常规类的子类型继承遵循此规则:如果B扩展A,则类B是类A的子类型。此规则不适用于泛型类型:

    1. List<B> lb = new ArrayList<>();
    2. List<A> la = lb; // compile-time error

    给定Integer是Number的子类型,List 和List 之间是什么关系?
    通配符和子类型 - 图1
    公共父级是List <?>。
    尽管Integer是Number的子类型,但List 不是List 的子类型,实际上,这两种类型无关。List 和List 的公共父级是List <?>。
    为了在这些类之间创建关系,以便代码可以通过List 的元素访问Number的方法,请使用上界通配符:

    1. List<? extends Integer> intList = new ArrayList<>();
    2. List<? extends Number> numList = intList; // OK. List<? extends Integer> is a subtype of List<? extends Number>

    因为Integer是Number的子类型,并且numList是Number对象的列表,所以intList(一个Integer对象的列表)和numList之间现在存在关系。下图显示了使用上下界通配符声明的几个List类之间的关系。
    通配符和子类型 - 图2
    几个泛型List类声明的层次结构。
    通配符使用准则部分有关使用上下界通配符的后果的详情。