2013-09-24 35 views
0

爲什麼我無法將對象添加到集合中?由於B類的東西,因爲以下原因延伸A.無法將實現接口A的對象添加到Collection中<? extends A>

import java.util.*; 

public class TestGeneric 
{ 
    public static void main(String[] args) 
    { 
    Collection<? extends A> collection = new ArrayList<A>(); 
    A a = new B(); 
    collection.add(a); 
    } 

    private static class B implements A { 
    public int getValue() { return 0; } 
    } 
} 

interface A { int getValue(); } 
+0

可能的重複[無法用通配符泛型添加值到Java集合](http://stackoverflow.com/questions/3716920/cant-add-value-to-the-java-collection-with-通配符 - 通用型)。另請參閱:[Java泛型:什麼是PECS?](http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs) –

回答

4

Collection<? extends A> coll = new ArrayList<C>(); // C extends A 

coll.add(new B()); // B extends A, but doesn't extend C. Oops. 

然而,由於編譯器知道科爾只具有延伸的A元素,您仍然可以檢索它們作爲。

A myA = coll.get(); // No problem, it might be B or C, but they both extend A 
2

請記住:Provider extends consumer super(又稱PECS)

你想東西到集合,所以集合爲一個消費者

Collection<? super A> collection = new ArrayList<A>(); 

this答案

案例2:你要的東西添加到集合。 然後列表是一個消費者,所以你應該使用Collection<? super Thing>

這裏的推理是,與Collection<? extends Thing>不同,Collection<? super Thing>可以始終保持Thing,不管實際的參數化類型是什麼。這裏你不關心列表中已有的內容,只要它允許添加Thing;這是? super Thing保證。

1

如果你有<? extends A>那麼此時編譯器不知道什麼是習慣的A的子類。因此,除了null之外,向集合中添加任何對象都是不安全的。

您不能將任何對象添加到List<? extends T>,因爲你不能保證什麼樣的名單是真的指向,所以你不能保證該對象被允許在該列表中。唯一的「保證」是你只能讀取它,你會得到一個Tsubclass of T

List<? extends Number>可以通過三種實現:

List<? extends Number> list = new ArrayList<Number>(); //數 「擴展」 號 List<? extends Number> list = new ArrayList<Integer>(); // Integer擴展號碼 List<? extends Number> list = new ArrayList<Double>(); //雙延伸數

所以,如果它是new ArrayList<Double>()和你加上integer,所以這是一個錯誤,所以編譯器將訪問權限限制爲只讀取不添加是安全的。

和增加也是安全的,因爲我們知道父類,因此我們可以將任意子類的父類引用如下:

Parent p = new Child(); //這是安全

因此在List<? extends Number>我們知道所有的集合中的元素以某種方式擴展Number因此我們可以閱讀它,因爲我們可以將子類的實例分配給父類引用。

1

短期和簡單的解釋:

<? extends A>手段:一些特定但未知擴展A類型。可能是A本身或其任何亞型。因此,您不能在此集合中插入任何元素:編譯器無法知道哪種類型對於add(object)方法的參數合法。