2011-09-09 88 views
3

我有讓我的頭周圍的仿製藥在下列情況下的問題,請參見在線評論下面我的問題:泛型集合和通配符的Java

public void exampleMethod() { 
    //Intuitively I would expect this to mean that test is set containing objects 
    //that subclass AbstractGroup 
    Set<? extends AbstractGroup> test; 

    //Yet the compiler complains here and I do not understand why? 

    test.add(new AnyAbstractGroupSubGroup()); 

    //I would guess that a method call such as this at runtime 

    test = new HashSet<SubGroupA>() 

    //would mean that only objects of subgroupA can be added to the collection, but then 
    //what is the point in using the wildcard in the first place? 
} 
+0

抱怨,怎麼樣? – Raedwald

回答

6
//Intuitively I would expect this to mean that test is set containing objects 
//that subclass AbstractGroup 
Set<? extends AbstractGroup> test; 

不,這意味着它是一組一個具體?它擴展了AbstractGroup。你和編譯器都沒有辦法知道那是什麼?是的,所以你無法向該組添加任何東西。

您可以將該集的值分配給AbstractGroup類型的變量,但不能以其他方式分配。

相反,你需要這樣的:

Set<? super AbstractGroup> test; 

這個原理有時也被稱爲PECS和解釋以及in this answer

2

你不需要通配符在這裏對你來說就足夠了說

Set<AbstractGroup> test; 

然後你可以把AbstractGroup的任何子類入套。

此外,它看起來並不像你在上面的代碼中初始化測試。

4

Set<? extends AbstractGroup> test;

這意味着你的設置可以是一組擴展AbstractGroup任何對象,但通常是編譯器不會讓你的東西添加到該集(因爲它不能告訴是否你會舉個例子,把SubGroupB加到Set<SubGroupA>等等)。

test = new HashSet<SubGroupA>()

您的實際集將只包含SubGroupA類型的對象和亞類的化合物。 但是,編譯器仍然不知道test的內容是什麼(參見上文)。

外卡的一點是:你可以在任何一組分配給被參數與AbstractGroup或子類的變量,從而保證你可以施放的所有對象已經映射到AbstractGroup(這對於編譯器檢查)。

如果您想擁有一個可包含任何AbstractGroup對象的集合,請不要使用通配符。

//this would compile (under the assumption that SubGroupA extends AbstractGroup) 
Set<? extends AbstractGroup> test = new HashSet<SubGroupA>(); 

//this wouldn't compile, since the compiler doesn't know the type of test (it might change at runtime etc.) 
test.add(new SubGroupA()); 


//this wouldn't compile since AbstractGroup and SubGroupA are not the exact same type (hence the wildcard would be needed here) 
Set<AbstractGroup> test = new HashSet<SubGroupA>(); 

//this would compile 
Set<AbstractGroup> test = new HashSet<AbstractGroup>(); 
test.add(new SubGroupA());