通配符和子类型

泛型,继承和子类型中所述,泛型类或interface之所以不相关,仅仅是因为它们的类型之间存在关系。但是,您可以使用通配符在通用类或interface之间创建关系。

给定以下两个常规(非泛型)类:

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

编写以下代码是合理的:

B b = new B();
A a = b;

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

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

假设IntegerNumber的子类型,List\<Integer\>List\<Number\>之间的关系是什么?

diagram showing that the common parent of List and List is the list of unknown type

共同的 parent 是List\<?\>

尽管IntegerNumber的子类型,但List\<Integer\>不是List\<Number\>的子类型,实际上,这两种类型无关。 List\<Number\>List\<Integer\>的公共父级是List\<?\>

为了在这些类之间创建关系,以便代码可以通过List\<Integer\>的元素访问Number的方法,请使用上限通配符:

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

因为IntegerNumber的子类型,并且numListNumber的对象列表,所以intList(Integer的对象列表)和numList之间存在关系。下图显示了使用上限和下限通配符声明的几个List类之间的关系。

diagram showing that List is a subtype of both List. List is a subtype of List.

几个通用List类声明的层次结构。

通配符使用准则部分提供有关使用上限和下限通配符的后果的更多信息。