如 泛型,继承和子类型中所述,泛型类或泛型接口不仅仅因为它们的类型之间存在关系而相关。但是,您可以使用通配符在泛型类或泛型接口之间创建关系。
给定以下两个常规(非泛型)类:
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
给定Integer是Number的子类型,List
公共父级是List <?>。
尽管Integer是Number的子类型,但List
为了在这些类之间创建关系,以便代码可以通过List
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类之间的关系。
几个泛型List类声明的层次结构。
通配符使用准则部分有关使用上下界通配符的后果的详情。