通配符和子类型
如泛型,继承和子类型中所述,泛型类或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
假设Integer
是Number
的子类型,List\<Integer\>
和List\<Number\>
之间的关系是什么?
共同的 parent 是List\<?\>
。
尽管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
类之间的关系。
几个通用List
类声明的层次结构。
通配符使用准则部分提供有关使用上限和下限通配符的后果的更多信息。