Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
如 Generics, Inheritance, and Subtypes 中所述,泛型类或接口不相关,仅仅是因为它们的类型之间存在关系。但是,你可以使用通配符在泛型类或接口之间创建关系。
给定以下两个常规(非泛型)类:
class A { /* ... */ } class B extends A { /* ... */ }
编写以下代码是合理的:
B b = new B(); A a = b;
此示例显示常规类的继承遵循此子类型规则:如果 B 继承(extends) A,则 B 是 A 的子类型。此规则不适用于泛型类型:
List<B> lb = new ArrayList<>(); List<A> la = lb; // compile-time error
假设 Integer 是 Number 的子类型,那么 List<Integer> 和 List<Number> 之间的关系是什么呢?
虽然 Integer 是 Number 的子类型,但 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>
因为 Integer 是 Number 的子类型,并且 numList 是 Number 对象的列表,所以现在 intList(Integer 对象的列表)和 numList 之间存在关系。下图显示了使用上界和下界通配符声明的几个 List 类之间的关系。
Guidelines for Wildcard Use 部分提供了有关使用上界和下界通配符的后果的更多信息。