java 泛型协方差

2022-09-01 21:54:05

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

泛型不是协变的

作者指出,

因为 ln 是一个列表,所以添加 Float 似乎是完全合法的。但是,如果 ln 与 li 混叠,那么它将打破 li 定义中隐含的类型安全承诺 - 它是整数列表,这就是为什么泛型类型不能是协变的原因。

我无法理解它说“如果ln与li别名”的部分。作者的别名是什么意思?(参考资料?引号行上方的代码片段似乎说明了Java中什么是非法的,而不是为什么。如果有人能用一个例子来解释,那对我来说会很有帮助。提前致谢。


答案 1
List<Integer> li = new ArrayList<Integer>();
List<Number> ln = li; // illegal
ln.add(new Float(3.1415));

在Java中,Integer继承自Number,因此直观地说,任何整数也是一个数字,但该文章指出的是,对于泛型,它不能以这种方式工作,因为考虑到这个例子,你最终可能会将浮点数(这是一个数字)放入一个,这是非法的,因为浮点数不是整数。(java.lang.Number)(java.lang.Integer)List<Integer>

结论:泛型不是协变的。

注意:我建议您阅读 Effective Java(第 2 版)第 5 章:泛型。


答案 2

如果您可以执行类似操作:

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

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

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

事情会变得非常错误。在此示例中,bar 是 foo 的别名,如果可以这样做,您将失去类型安全性,这是泛型存在的主要原因。


推荐