23

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

在下面,

泛型不是协变的

作者说,

因为 ln 是一个 List,向它添加一个 Float 似乎是完全合法的。但是如果 ln 用 li 作为别名,那么它会破坏 li 定义中隐含的类型安全承诺——它是一个整数列表,这就是泛型类型不能协变的原因。

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

4

3 回答 3

50
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)也是一个数字,但那篇文章指出的是,使用泛型它不能那样工作,因为考虑到那个例子,你最终可能会放一个浮点数(这是一个数字)转换为 a List<Integer>,这是非法的,因为浮点数不是整数。

结论:泛型不是协变的。

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

于 2010-04-18T02:17:24.780 回答
10

如果你能做这样的事情:

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

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

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

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

于 2010-04-18T02:15:57.910 回答
-2
public class vechicle {
void drive(){
}
}
class car extends vechicle{
        //Covariance
    vechicle getObject(){
        return new car();
    }
        //contravariance
    car getmyObject(){
        return (car) new vechicle(); 
    }
}
于 2014-03-05T04:39:47.587 回答