【问题标题】:Java list generics with multiple bounds具有多个边界的 Java 列表泛型
【发布时间】:2015-09-29 08:57:03
【问题描述】:

我很难理解为什么以下代码不起作用:

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 满足这些条件,为什么它不起作用?

谢谢

【问题讨论】:

  • 我可以调用YourClass.&lt;Cat&gt;testFunction(),然后您的函数会创建一个ArrayList&lt;Cat&gt; 并向其中添加一个Dog。
  • 哈,我现在看到了逻辑中的缺陷,然后我修改了它:code public void testFunction(E var) { List list = new数组列表(); list.add(var); } code 并称之为:code Dog var = new Dog();测试函数(变量); code 这很有效,更有意义,谢谢:)
  • 如果你把元素作为参数,像这样:public &lt;E extends Animal &amp; IQuadruped&gt; void testFunction(E var),它会起作用。

标签: java list generics collections bounds


【解决方案1】:

&lt;E extends Animal &amp; IQuadruped&gt; 的意思是“作为AnimalIQuadruped 子类型的特定类型”,而不是“作为AnimalIQuadruped 子类型的任何类型”

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

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

明显的错误解决方案是指定&lt;E extends Dog&gt;,因为它会保证EDog 的子类型。但是由于完全相同的原因这是错误的,E 可以是Dog 的任何子类型,假设EPoodle,所以当您创建List&lt;Poodle&gt; 时,您将无法放置你的new Dog() 在那里,因为它不是Poodle

正确的界限是&lt;E super Dog&gt;,因为这意味着E 绝对是您可以将Dog 实例强制转换为的类型。它可能是Dog 本身,也可能是AnimalIQuadruped 甚至Object。但它保证您可以在列表中添加Dog

这个原理的名称是PECS:producer extends,consumer super,你可以阅读它here

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 即使没有类型擦除,这也是无效的。问题在于协变和逆变。
    • 我对此表示反对,因为该问题与类型擦除无关。 (不过,如果他尝试做new E(),情况就是这样)
    猜你喜欢
    • 2016-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多