2014-10-09 89 views
1

假設我有一個列表定義如下。Java泛型和繼承:無法添加到列表

private List<? extends GeneralBudgetYearBean> budgetYearBeans; 

// + Getters/setters... 

爲什麼我無法泛指名單這一類的外部如下:

GeneralBudgetYearBean gbyb; 
getBudgetYearBeans().add(bgyb); 

的錯誤是:

The method add(capture#6-of ? extends GeneralBudgetYearBean) in the type List<capture#6-of ? extends GeneralBudgetYearBean> is not applicable for the arguments (GeneralBudgetYearBean) 

這是沒有意義的。是否因爲「擴展T」與「T」不一樣,並且「T」在這裏不能被替換?

我需要能夠通常操縱這個類沒有具體細節。在某些時候,會有一個在擴展類中構造的「SUBGeneralBudgetYearBeans」的ArrayList,這就是爲什麼我需要使用「?extends GeneralBudgetYearBean」表示法。

+0

怎麼樣'List '? – sp00m 2014-10-09 14:22:14

+0

@ sp00m我不能使用它。正如我所說的,在某個時候會構建一個ArrayList ,並且「擴展」表示法是實現這一點的唯一方法。 – 2014-10-09 14:23:39

+2

http://stackoverflow.com/questions/11119804/adding-objects-to-the-extends-type-of-generic-collections – marcinj 2014-10-09 14:31:42

回答

0

按照PESC原則:

使用時,只需要獲取對象和超時只需要添加對象延伸。

在你的情況下,

private List<? extends GeneralBudgetYearBean> budgetYearBeans; 

生產,這意味着該列表將只能夠產生元素。原因是在編譯時編譯器不知道GeneralBudgetYearBean的子類型,這就是爲什麼它不允許添加元素,因爲它不能完全確定是否允許你。

既然你(在某種程度上)也加入SubBudgetYearBean對象(這我相信是GeneralBudgetYearBean子類),你必須創建列表作爲消費者。因此,這會爲你工作:

private List<? super SubBudgetYearBean> budgetYearBeans; 

在這種情況下,你將能夠實例budgetYearBean爲:

budgetYearBeans = new ArrayList<Object>(); 
budgetYearBeans = new ArrayList<GeneralBudgetYearBean>(); 

在這兩種情況下,你就可以同時添加GeneralBudgetYearBeanSubBudgetYearBean對象。

0

當您使用表達式List<? extends GeneralBudgetYearBean> budgetYearBeans;時,告訴編譯器該變量稍後將收到一個List,其中X將延伸到GeneralBudgetYearBean。但它不知道它將是什麼類,因此如果不允許你添加任何東西。

可以使當前的類通用:

class xxx<T extends GeneralBudgetYearBean> { 
    private List<T> budgetYearBeans; // getter and setter 

然後,你將被允許做:

T gbyb; 
getBudgetYearBeans().add(bgyb); 

,因爲現在你告訴編譯器:你不知道它到底會是什麼,但它將是同樣的事情。

0

放棄通配符,在這種情況下它們不會真正幫助你,除非你真的知道自己在做什麼,否則它們只會使事情複雜化。

private List<GeneralBudgetYearBean> budgetYearBeans = ... 

public List<GeneralBudgetYearBean> getBudgetYearBeans() { 
    return budgetYearBeans; 
} 

因爲SUBGeneralBudgetYearBean延伸GeneralBudgetYearBean,那麼,這是要麼將它們添加到列表中的一個沒有問題... ...

SUBGeneralBudgetYearBean sgyb = ... 
getBudgetYearBeans().add(sgyb); 

...或列表...

List<SUBGeneralBudgetYearBean> sgybs = ... 
getBudgetYearBeans().addAll(sgybs); 

請參閱?實際上不需要通配符。 :)

+0

不,不是這種情況。在擴展類中,我必須這樣做: setBudgetYearBeans(new ArrayList ())。這給出了一個錯誤。 – 2014-10-09 15:49:24

+0

然後不要使用setter作爲列表。只需使用'getBudgetYearBeans()。clear()'和getBudgetYearBeans()。addAll(subBudgetBeans)''。 – Natix 2014-10-09 15:56:19