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);
}

狗如下:

public class Dog extends Animal implements IQuadruped
{

}

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

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

我只想确保我的列表元素 extend/implement 类 和 Dog 都满足这些条件,为什么它不起作用?

谢谢

Generics type erasure 就是你得到的。当 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())
}

<E extends Animal & IQuadruped>的意思是"a particular type that is a subtype of both Animal and IQuadruped",而不是"any type that is a subtype of both Animal and IQuadruped"

之所以难以把握差异,是因为在日常思维中我们没有明确区分。例如,如果您同意与某人在餐厅共进午餐,而他们说 "any day next week is good for me",您会自动知道这意味着您需要在同一天出现。并不是说你可以随时去,他们会在那里。

在这种情况下,无法保证调用者选择的 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: producer extends, consumer super,你可以看看here