繁体   English   中英

具有多个界限的Java列表泛型

[英]Java list generics with multiple bounds

我正在努力理解以下代码为何不起作用:

public <E extends Animal & IQuadruped> void testFunction()
{
    List<E> list = new ArrayList<E>();
    Dog var = new Dog();
    list.add(var);
}

其中Dog为以下内容:

public class Dog extends Animal implements IQuadruped
{

}

我在添加时遇到编译错误:

The method add(E) in the type List<E> is not applicable for the arguments (Dog)

我只想确保列表元素可以扩展/实现两个类,而Dog可以满足这些条件,为什么它不起作用?

谢谢

<E extends Animal & IQuadruped>意思是“既是AnimalIQuadruped的子类型的特定类型”,又不是“任何同时是AnimalIQuadruped的子类型的类型”

难以理解差异的原因是,在日常思考中,我们并未明确区分。 例如,如果您同意与某人在一家餐馆共进午餐,并且他们说“下周的任何一天对我都有好处”,您会自动知道这意味着您需要在同一天上班。 并不是说您可以随时去,他们会在那里。

在这种情况下,不能保证呼叫者选择的E肯定是Dog ,因此您的代码将无法工作。

明显的错误解决方案是指定<E extends Dog> ,因为它将保证EDog的子类型。 但是由于完全相同的原因这是错误的, E可以是Dog任何子类型,假设E是一个Poodle ,因此当您创建List<Poodle> ,将无法在其中放置new Dog() ,因为它不是Poodle

正确的界限是<E super Dog> ,因为这意味着E绝对是可以将Dog实例强制转换为的类型。 它可能是Dog本身,可能是AnimalIQuadruped甚至是Object 但它保证您可以在列表中放入“ Dog ”。

该原则的名称是PECS:生产者扩展,消费者超级,您可以在此处阅读。

泛型类型擦除就是您所得到的。 当JVM执行要添加到列表中的行时,泛型已经丢失。 要使其正常工作,您必须执行以下操作:

public <E extends Animal & IQuadruped> void testFunction(E param) {
    List<E> list = new ArrayList<E>();
    list.add(param);
}

public void addDog() {
    testFunction(new Dog())
}

暂无
暂无

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

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