泛型,继承和子类型

众所周知,只要类型兼容,就可以将一种类型的对象分配给另一种类型的对象。例如,您可以将Integer分配给Object,因为ObjectInteger的超类型之一:

Object someObject = new Object();
Integer someInteger = new Integer(10);
someObject = someInteger;   // OK

在面向对象的术语中,这称为“是”关系。由于Integer Object的一种,因此允许分配。但是Integer也是Number的一种,因此以下代码也有效:

public void someMethod(Number n) { /* ... */ }

someMethod(new Integer(10));   // OK
someMethod(new Double(10.1));   // OK

泛型也是如此。您可以执行泛型调用,将Number作为其类型参数,如果该参数与Number兼容,则以后可以再调用add

Box<Number> box = new Box<Number>();
box.add(new Integer(10));   // OK
box.add(new Double(10.1));  // OK

现在考虑以下方法:

public void boxTest(Box<Number> n) { /* ... */ }

它接受哪种类型的论点?通过查看其签名,您可以看到它接受一个类型为Box\<Number\>的单个参数。但是,这是什么意思?您是否可以像预期的那样通过Box\<Integer\>Box\<Double\>?答案为“否”,因为Box\<Integer\>Box\<Double\>不是Box\<Number\>的子类型。

在使用泛型进行编程时,这是一个常见的误解,但这是一个重要的学习概念。

diagram showing that Box is not a subtype of Box

`Box\<Integer\>`  is not a subtype of  `Box\<Number\>`  even though  `Integer`  is a subtype of  `Number` \.  

Note:

给定两个具体类型AB(例如NumberInteger),则MyClass\<A\>MyClass\<B\>没有关系,无论AB是否相关。 MyClass\<A\>MyClass\<B\>的共同父对象是Object

有关在类型参数相关时如何在两个泛型类之间创建类似子类型的关系的信息,请参见通配符和子类型

通用类和子类型

您可以通过扩展或实现来泛型通用类或interface。一个类或interface的类型参数与另一类或interface的类型参数之间的关系由extendsimplements子句确定。

Collections类为例,ArrayList\<E\>实现List\<E\>List\<E\> extends Collection\<E\>。因此ArrayList\<String\>List\<String\>的子类型,而List\<String\>Collection\<String\>的子类型。只要您不改变类型参数,子类型关系就保留在类型之间。

diagram showing a sample collections hierarchy: ArrayList is a subtype of List, which is a subtype of Collection.

Collections层次结构示例

现在,假设我们要定义自己的列表interfacePayloadList,它将泛型P的可选值与每个元素相关联。它的声明可能看起来像:

interface PayloadList<E,P> extends List<E> {
  void setPayload(int index, P val);
  ...
}

以下PayloadList的参数化是List\<String\>的子类型:

  • PayloadList\<String,String\>

  • PayloadList\<String,Integer\>

  • PayloadList\<String,Exception\>

diagram showing an example PayLoadList hierarchy: PayloadList<String, String> is a subtype of List, which is a subtype of Collection. At the same level of PayloadList<String,String> is PayloadList<String, Integer> and PayloadList<String, Exceptions>.

PayloadList层次结构示例