“嗨!我要繼續艾莉的泛型課程。準備好聽了嗎?”
“是的。”
“那我們開始吧。”
“首先你需要知道的是,一個類的方法也可以有自己的類型參數。”
“我知道。”
“不,我特指自己的類型參數: ”
class Calculator
{
T add(T a, T b); // Add
T sub(T a, T b); // Subtract
T mul(T a, T b); // Multiply
T div(T a, T b); // Divide
}
“這些類型參數專門與方法有關。該類沒有參數。您甚至可以將這些方法聲明為靜態的,並在沒有對象的情況下調用它們。”
“我明白了。方法中的類型參數的意義與類相同?”
“是的。但是有一些新東西。”
“正如你已經知道的,你可以在類型聲明中使用通配符。那麼想像一下以下情況:”
public void doSomething(List<? extends MyClass> list)
{
for(MyClass object : list)
{
System.out.println(object.getState()); // Everything works well here.
}
}
“但是如果我們想向集合中添加一個新項目怎麼辦:”
public void doSomething(List<? extends MyClass> list)
{
list.add(new MyClass()); // Error!
}
“問題是,在一般情況下,doSomething 方法可能會傳遞一個列表,其元素不是 MyClass 對象,而是 MyClass 的任何子類的對象。但是你不能將 MyClass 對象添加到這樣的列表中!”
“啊。那麼,那有什麼辦法呢?”
“沒什麼。在這種情況下,你什麼也做不了。但這給了 Java 的創造者一些思考。他們想出了一個新的關鍵字:super。”
“語法看起來幾乎一樣:”
List<? super MyClass> list
但是 extends 和 super 之間有一個重要的區別。
“«? extends T» 意味著該類必須是 T 的後代。”
“«?super T» 意味著該類必須是 T 的祖先。”
“我的天啊。那這東西用在什麼地方?”
“«? super T» 在方法涉及添加到 T 對象的集合時使用。在這種情況下,它可以是 T 對象的集合或 T 的任何祖先。”
“啊。可以將 AT 對象分配給類型為 T 的任何祖先的引用變量”
“老實說,這種方式用得併不多,而且還有一個缺點,比如:”
public void doSomething(List<? super MyClass> list)
{
for(MyClass object : list) // Error!
{
System.out.println(object.getState());
}
}
public void doSomething(List<? super MyClass> list)
{
list.add(new MyClass()); // Everything works well here.
}
“現在第一個例子行不通了。”
“因為 list 甚至可以是 List<Object>(Object 是 MyClass 的最頂層超類),我們實質上是在編寫以下無效代碼:”
List<Object> list;
for(MyClass object : list) // Error!
{
System.out.println(object.getState());
}
“我明白了。謝謝你有趣的課。”
“不客氣。”
GO TO FULL VERSION