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>
,因为它会保证E
是Dog
的子类型。然而,由于完全相同的原因,这是错误的,E
可以是 Dog
的任何子类型,假设 E
是一个 Poodle
,所以当你创建一个 List<Poodle>
, 你不能把你的 new Dog()
放在那里,因为它不是 Poodle
.
正确的界限是 <E super Dog>
,因为这意味着 E
绝对是可以将 Dog
实例转换为的类型。它可以是 Dog
本身,也可以是 Animal
或 IQuadruped
甚至 Object
。但是它保证你可以在列表中放一个Dog
。
这个原则的名字叫PECS: producer extends, consumer super,你可以看看here。
我很难理解为什么以下代码不起作用:
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>
,因为它会保证E
是Dog
的子类型。然而,由于完全相同的原因,这是错误的,E
可以是 Dog
的任何子类型,假设 E
是一个 Poodle
,所以当你创建一个 List<Poodle>
, 你不能把你的 new Dog()
放在那里,因为它不是 Poodle
.
正确的界限是 <E super Dog>
,因为这意味着 E
绝对是可以将 Dog
实例转换为的类型。它可以是 Dog
本身,也可以是 Animal
或 IQuadruped
甚至 Object
。但是它保证你可以在列表中放一个Dog
。
这个原则的名字叫PECS: producer extends, consumer super,你可以看看here。