繁体   English   中英

Java泛型和继承:无法添加到列表

[英]Java Generics & Inheritance: Unable to add to List

假设我有一个List定义,如下所示。

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)

这没有道理。 是否因为“?extends T”与“ T”不同,并且不能在此处替换“ T”?

我需要通常能够在没有细节的情况下操纵此类。 在某个时候,将在扩展类中构造一个“ SUBGeneralBudgetYearBeans”的ArrayList,这就是为什么我需要使用“?extended GeneralBudgetYearBean”表示法的原因。

根据PESC原则:

当只需要获取对象时,使用扩展;当只需要添加对象时,使用扩展。

就您而言,

private List<? extends GeneralBudgetYearBean> budgetYearBeans;

生产者 ,这意味着列表将只能产生元素。 原因是在编译时,编译器不知道GeneralBudgetYearBean的子类型,这就是为什么它不让您添加元素的原因,因为不能完全确定是否允许您。

由于您还将(在某个时候)添加SubBudgetYearBean对象(我相信这是GeneralBudgetYearBean子类),因此您必须将列表创建为使用者 因此,这将为您工作:

private List<? super SubBudgetYearBean> budgetYearBeans;

在这种情况下,您将能够实例化budgetYearBean为:

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

在这两种情况下,您都可以添加GeneralBudgetYearBeanSubBudgetYearBean对象。

当您使用表达式List<? extends GeneralBudgetYearBean> budgetYearBeans; List<? extends GeneralBudgetYearBean> budgetYearBeans; ,您告诉编译器该变量以后将收到一个List,其中X将扩展GeneralBudgetYearBean 但是它不知道它将是什么类,因此,如果不允许,则不能在其中添加任何内容。

您可以使当前类通用:

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

然后,您将被允许做:

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

因为现在您告诉编译器:您不完全知道它将是什么,但是会是同一回事。

删除通配符,在这种情况下它们不会真正为您提供帮助,它们只会使事情复杂化,除非您真的知道自己在做什么。

private List<GeneralBudgetYearBean> budgetYearBeans = ...

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

因为SUBGeneralBudgetYearBean扩展了GeneralBudgetYearBean ,所以将它们添加到列表中一个都没有问题。

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

...或作为清单...

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

看到? 实际上不需要通配符。 :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM