如你所知,只要類型兼容,就能夠將一種類型的對象分配給另外一種類型的對象,例如,你能夠將Integer
分配給Object
,由於Object
是Integer
的超類型之一:編程
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
給定兩個具體類型A
和B
(例如,Number
和Integer
),MyClass<A>
與MyClass<B>
無關,不管A
和B
是否相關,MyClass<A>
和MyClass<B>
的公共父級是Object
。有關如何在類型參數相關時在兩個泛型類之間建立相似子類型關係的信息,請參閱通配符和子類型。對象
你能夠經過擴展或實現泛型類或接口來對其進行子類型化,一個類或接口的類型參數與另外一個類或接口的類型參數之間的關係由extends
和implements
子句肯定。blog
使用Collections
類做爲示例,ArrayList<E> implements List<E>
,List<E> extends Collection<E>
,所以ArrayList<String>
是List<String>
的子類型,也是Collection<String>
的子類型,只要不改變類型參數,就會在類型之間保留子類型關係。繼承
如今假設咱們想要定義咱們本身的列表接口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>