【问题标题】:overriding list result type in java覆盖java中的列表结果类型
【发布时间】:2010-09-10 19:46:22
【问题描述】:

我想在 java 中编译这段代码的一些变体。

class X
{
    List<X> getvalue(){...};
}

class Y extends X
{
    List<Y> getvalue(){...};
}

Javac (1.6) 返回错误,因为 List 和 List 不兼容。

关键是我希望编译器 认识到 List 是兼容的返回 如果 Y 是 X 的子类型,则键入 List。 我想要这个的原因是为了简化用户定义工厂类的使用。

注意:这个问题有点像 this question 但是对于java。

【问题讨论】:

标签: java generics list overriding


【解决方案1】:

在 Java 中,覆盖方法的返回类型必须与被覆盖方法的返回类型一致。

java.util.List 类不是协变的(事实上,没有 Java 类是协变的。发生这种情况是因为缺少声明站点方差注释)。换句话说,B &lt;: A 并不暗示List&lt;B&gt; &lt;: List&lt;A&gt;(将&lt;: 读作is-subtype-of)。因此您的代码不会进行类型检查。


在 Java 中,您有定义站点的差异。因此,以下类型检查:

import java.util.List;

class X {
  List<? extends X> getvalue() { return null; }
}

class Y extends X {
  List<Y> getvalue() { return null; }
}

【讨论】:

    【解决方案2】:

    不,它不是兼容的类型。您不能仅仅因为YX 的子类而从List&lt;Y&gt; 转换为List&lt;X&gt;。考虑:

    List<Banana> bananas = new ArrayList<Banana>();
    List<Fruit> fruit = bananas;
    fruit.add(new Apple());
    Banana banana = fruit.get(0); // But it's an apple!
    

    您可以在 Java 中使用有界通配符来表示有限的方差,给出 有效的东西:

    List<? extends Fruit> fruit = bananas;
    

    因为这会阻止您(在编译时)尝试添加任何额外的水果 - 编译器知道它可能是无效的。

    我会推荐 Angelika Langer 的 Java Generics FAQ 以进一步阅读这类事情。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-17
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多