【问题标题】:java generics covariancejava泛型协方差
【发布时间】:2011-02-09 06:57:06
【问题描述】:

我无法理解以下文章: http://www.ibm.com/developerworks/java/library/j-jtp01255.html

下,

泛型不是协变的

作者说,

因为 ln 是一个 List,所以添加一个 浮动到它似乎完全合法。但 如果 ln 与 li 别名,那么它 会破坏类型安全承诺 隐含在 li 的定义中—— 它是一个整数列表,其中 这就是为什么泛型类型不能 协变。

我无法理解它所说的部分 “如果 ln 别名为 li”。作者所说的别名是什么意思?(参考?)。引用行上方的代码 sn-p 似乎说明了在 java 中什么是非法的,而不是为什么。如果有人可以举例说明,那对我很有帮助。 提前致谢。

【问题讨论】:

  • IIRC,泛型类型不是协变的,因为它们无法改变数组在以前版本的 Java 中的实现/使用方式(向后兼容),这是否对某人敲响了警钟?
  • @Skeptic,数组是协变泛型实现的一个例子——它会抛出运行时异常。 Java 无法做到这一点,因为泛型在运行时会被擦除,所以它只能通过限制协方差来控制它。
  • @Yishai,Steele 在名为“Growing a Language”的演示文稿中讨论了数组的问题,我现在似乎找不到。
  • IBM 链接似乎已失效,但在 Wayback Machine 上有一个副本:web.archive.org/web/20121104021805/http://www.ibm.com/…
  • @Skeptic 斯蒂尔演示文稿的书面版本没有提到阵列问题。不过,读起来还是很不错的。它位于cs.virginia.edu/~evans/cs655/readings/steele.pdf 或通过Wayback 机器web.archive.org/web/20131117030438/http://www.cs.virginia.edu/…

标签: java generics alias covariance


【解决方案1】:
List<Integer> li = new ArrayList<Integer>();
List<Number> ln = li; // illegal
ln.add(new Float(3.1415));

在 Java 中,Integer 继承自 Number(java.lang.Number),所以直观地说,任何 Integer(java.lang.Integer) 也是一个数字,但那篇文章指出,使用泛型它不能那样工作,因为考虑到例如,您最终可能会将浮点数(它是一个数字)放入 List&lt;Integer&gt;,这是非法的,因为浮点数不是整数。

结论:泛型不是协变的。

注意:我推荐你阅读Effective Java (2nd Edition) Chapter 5: Generics。

【讨论】:

  • 谢谢。 8)我认为解释与代码sn-p无关。傻我。
  • +1 用于记录阅读 Effective Java。我已经写代码很多年了,一个月前学习了 EJ,并立即学习了 5 或 6 个非常重要的策略。
  • 有点离题,但 C# 确实允许集合以安全的方式具有某种协方差。结帐mikehadlow.blogspot.co.uk/2009/10/…
  • 那么,如果我有一个返回类型List&lt;Number&gt; 的方法,我原则上可以安全地返回List&lt;Integer&gt;,因为整数列表之后将不再被引用? (不是说java没有警告就支持这个)
【解决方案2】:

如果你可以这样做:

List<Float> foo;
List<Object> bar;

foo = new ArrayList<Float>();
bar = foo;

foo.add(1.0f);
bar.add("Hello");

事情会大错特错。在这个例子中,bar 是 foo 的别名,如果你能这样做,你将失去类型安全性,而这是泛型存在的主要原因。

【讨论】:

  • 非常感谢。我不确定别名部分。这证实了我的假设是正确的。
  • 啊!所以现在“你好”不仅在bar 中(这可能没问题),而且在foo 中。最后它是有道理的:) 我想我可以声明一个列表转换方法,它必须复制列表,嗯。
【解决方案3】:
public class vechicle {
void drive(){
}
}
class car extends vechicle{
        //Covariance
    vechicle getObject(){
        return new car();
    }
        //contravariance
    car getmyObject(){
        return (car) new vechicle(); 
    }
}

【讨论】:

  • java.lang.ClassCastException 将在 return (car) new vechicle(); 引发
猜你喜欢
  • 1970-01-01
  • 2020-11-20
  • 1970-01-01
  • 2012-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多