2014-10-09 84 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