[英]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>
意思是“既是Animal
和IQuadruped
的子类型的特定类型”,又不是“任何同时是Animal
和IQuadruped
的子类型的类型”
难以理解差异的原因是,在日常思考中,我们并未明确区分。 例如,如果您同意与某人在一家餐馆共进午餐,并且他们说“下周的任何一天对我都有好处”,您会自动知道这意味着您需要在同一天上班。 并不是说您可以随时去,他们会在那里。
在这种情况下,不能保证呼叫者选择的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:生产者扩展,消费者超级,您可以在此处阅读。
泛型类型擦除就是您所得到的。 当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.