Java™ 教程(泛型、继承和子类型)

泛型、继承和子类型

如你所知,只要类型兼容,就能够将一种类型的对象分配给另外一种类型的对象,例如,你能够将Integer分配给Object,由于ObjectInteger的超类型之一:编程

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

在面向对象的术语中,这被称为“是一种”关系,因为Integer是一种Object,所以容许赋值,可是Integer也是一种Number,因此下面的代码也是有效的:segmentfault

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

如今考虑如下方法:spa

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

它接受什么类型的参数?经过查看其签名,你能够看到它接受一个类型为Box<Number>的参数,可是,这是什么意思?你是否能够按照预期传递Box<Integer>Box<Double>?答案是“否”,由于Box<Integer>Box<Double>不是Box<Number>的子类型。3d

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

generics-subtypeRelationship.gif

给定两个具体类型 AB(例如, NumberInteger), MyClass<A>MyClass<B>无关,不管 AB是否相关, MyClass<A>MyClass<B>的公共父级是 Object

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

泛型类和子类型

你能够经过扩展或实现泛型类或接口来对其进行子类型化,一个类或接口的类型参数与另外一个类或接口的类型参数之间的关系由extendsimplements子句肯定。blog

使用Collections类做为示例,ArrayList<E> implements List<E>List<E> extends Collection<E>,所以ArrayList<String>List<String>的子类型,也是Collection<String>的子类型,只要不改变类型参数,就会在类型之间保留子类型关系。继承

generics-sampleHierarchy.gif

如今假设咱们想要定义咱们本身的列表接口PayloadList,它将泛型类型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>

generics-payloadListHierarchy.gif


上一篇:有界类型参数

下一篇:类型推断

相关文章
相关标签/搜索