2015-07-10 66 views
1
Java的泛型列表

我挣扎理解为什么下面的代码不工作:具有多个限制

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) 

我只是想确保我的列表元素扩展/实现这两个类,狗完全填充那些cond itions,为什么它不起作用?

谢谢

+6

我可以调用'YourClass。 testFunction()',然后你的函数会创建一个'ArrayList '并添加一个Dog到它。 – immibis

+0

哈我现在看到的缺陷在逻辑,我修改它像然后: 'code' 公共空隙testFunction(E VAR) \t { \t \t 名单列表=新的ArrayList (); \t \t list.add(var); \t} 'code' 并把它称为: 'code' 狗VAR =新狗(); \t \t testFunction(var); 'code' 这样做的效果更好,谢谢:) – Th4n4to

+0

如果另一方面你把元素作为参数,就像这样:'public void testFunction(E var)',它会工作。 – biziclop

回答

0

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()) 
} 
+2

即使没有类型删除,这将是无效的。问题在于协方差和逆变。 – biziclop

+0

我对此表示怀疑,因为问题与类型删除无关。 (如果他试图做新的E(),情况就是这样) – immibis

1

什么<E extends Animal & IQuadruped>手段是“特定类型既AnimalIQuadruped的子类型”,而不是“任何类型,它是一个亚型AnimalIQuadruped

难以把握差异的原因在于,在日常思考中,我们没有明确区分。例如,如果您同意与餐厅的某人共进午餐,并且他们会说“下周的任何一天对我都有好处”,那么您会自动知道这意味着您需要在同一天内出现。而不是你可以随时去,他们会在那里。

在这种情况下,有没有保证,E呼叫者选择肯定会Dog,因此您的代码将无法正常工作。

明显错误解决方案是指定<E extends Dog>,因为这将保证EDog一个亚型。然而,这是错误的,因为完全相同的原因,E可能是Dog的任何子类型,假设EPoodle,所以当您创建List<Poodle>时,您将无法将new Dog()放在那里,因为它不是一个Poodle

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

这个原则的名字是PECS:生产者扩展,消费者超级,你可以阅读它here