當類的泛型相關時,如何在兩個泛型類之間創建類似子類型的關係

哈嘍大家好,我是阿Q!

事情是這個樣子的......

對話中的截圖如下:

看了阿Q的解釋,你是否也和“馬小跳”一樣存在疑問呢?請往👇看

我們都知道在java中,只要是類型兼容,就可以將一種類型的對象分配給另一種類型的對象。比如可以將一個Integer類型的對象分配給Object類型的對象,因爲ObjectInteger的超類。

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

在面向對象中,我們把它稱之爲 is a 的關係。因爲IntegerObject的一種子類,所以允許被賦值。

又因爲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>類型的參數可以傳入嗎?

答案是否定的。

儘管IntegerNumber的子類型,但Box<Integer>Box<Double>不是Box<Number>的子類,它倆的父類對象是Object文首的對話表達的就是這個意思。

那麼問題來了,當類的泛型相關時,如何在兩個泛型類之間創建類似子類型的關係呢?例如如何讓Box<Integer>Box<Double>變得與Box<Number>有關呢?

爲了搞懂這個問題,我們先來了解一下同一類型的對象是如何實現子類型化的吧。

通過分析源碼我們可以發現:ArrayList<E> 實現了 List<E>List<E> 繼承了Collection<E>,所以ArrayList<String>List<String>的子類型, List<String>Collection<String>的子類型。因此當我們在傳遞參數時,ArrayList<String>類型的是可以給List<E>或者Collection<E>傳遞的。

只要不改變類型參數,類型之間的子類型關係就會保留。

如果我們想要定義我們自己的列表接口PayloadList,使得泛型類型P的可選值與每個元素相關聯,可以定義如下:

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

PayloadList<String,String>PayloadList<String,Integer>PayloadList<String,Exception>都是List<String>的子類型。

小結:可以通過繼承泛型類或者實現接口來對其進行子類型化。

搞懂了子類型化的問題,我們回到“如何在兩個泛型類之間創建類似子類型的關係“的問題。

泛型類或者接口並不會僅僅因爲它們的類型之間有關係而變得相關,如果要達到相關,我們可以使用通配符來創建泛型類或接口之間的關係。

Box<Integer>Box<Number>的父類對象其實是Box<?>

爲了在這些類之間創建關係,以便代碼可以通過Box<Integer>訪問Box<Number>的方法,可以使用上限通配符:

Box<? extends Integer> initBox = new Box<>();
Box<? extends Number> numberBox = initBox;
// OK. Box<? extends Integer> is a subtype of Box<? extends Number>

因爲IntegerNumber的子類型,numberBox的泛型是Number對象子類,所以在intBoxnumberBox之間存在關係。

圖爲用上限下限通配符聲明的幾個類之間的關係。

所以,“馬小跳”的問題你會了嗎?還不會的話來技術羣交流吧!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章