2015-07-10 65 views
1
Java的泛型列表

我掙扎理解爲什麼下面的代碼不工作:具有多個限制

public <E extends Animal & IQuadruped> void testFunction() 
{ 
    List<E> list = new ArrayList<E>(); 
    Dog var = new Dog(); 
    list.add(var); 
} 

與狗爲以下幾點:

public class Dog extends Animal implements IQuadruped 
{ 

} 

而且我得到一個編譯錯誤上加:

The method add(E) in the type List<E> is not applicable for the arguments (Dog) 

我只是想確保我的列表元素擴展/實現這兩個類,狗完全填充那些cond itions,爲什麼它不起作用?

謝謝

+6

我可以調用'YourClass。 testFunction()',然後你的函數會創建一個'ArrayList '並添加一個Dog到它。 – immibis

+0

哈我現在看到的缺陷在邏輯,我修改它像然後: 'code' 公共空隙testFunction(E VAR) \t { \t \t 名單列表=新的ArrayList (); \t \t list.add(var); \t} 'code' 並把它稱爲: 'code' 狗VAR =新狗(); \t \t testFunction(var); 'code' 這樣做的效果更好,謝謝:) – Th4n4to

+0

如果另一方面你把元素作爲參數,就像這樣:'public void testFunction(E var)',它會工作。 – biziclop

回答

0

Generics type erasure是你做了什麼。在JVM執行添加到列表中的行時,泛型已經丟失。爲了得到這個工作,你就必須這樣做:

public <E extends Animal & IQuadruped> void testFunction(E param) { 
    List<E> list = new ArrayList<E>(); 
    list.add(param); 
} 

public void addDog() { 
    testFunction(new Dog()) 
} 
+2

即使沒有類型刪除,這將是無效的。問題在於協方差和逆變。 – biziclop

+0

我對此表示懷疑,因爲問題與類型刪除無關。 (如果他試圖做新的E(),情況就是這樣) – immibis

1

什麼<E extends Animal & IQuadruped>手段是「特定類型既AnimalIQuadruped的子類型」,而不是「任何類型,它是一個亞型AnimalIQuadruped

難以把握差異的原因在於,在日常思考中,我們沒有明確區分。例如,如果您同意與餐廳的某人共進午餐,並且他們會說「下週的任何一天對我都有好處」,那麼您會自動知道這意味着您需要在同一天內出現。而不是你可以隨時去,他們會在那裏。

在這種情況下,有沒有保證,E呼叫者選擇肯定會Dog,因此您的代碼將無法正常工作。

明顯錯誤解決方案是指定<E extends Dog>,因爲這將保證EDog一個亞型。然而,這是錯誤的,因爲完全相同的原因,E可能是Dog的任何子類型,假設EPoodle,所以當您創建List<Poodle>時,您將無法將new Dog()放在那裏,因爲它不是一個Poodle

正確的界限是<E super Dog>,因爲這意味着E絕對是您可以投入Dog實例的類型。它可能是Dog本身,它可能是AnimalIQuadruped甚至Object。但它保證您可以將Dog放入列表中。

這個原則的名字是PECS:生產者擴展,消費者超級,你可以閱讀它here