2010-04-18 67 views
19

我无法理解下面的文章: http://www.ibm.com/developerworks/java/library/j-jtp01255.htmlJava泛型协方差

下,

泛型不是协变

笔者状态,

因为ln是一个列表,添加一个浮在它似乎完全合法。但是,如果 LN用李别名,那么 将打破类型安全承诺 在李的定义隐含 - 它是一个整数列表,这 就是泛型类型不能 协变。

我不明白它说的部分 “如果ln被别名为li”。作者的意思是别名(参考?)。引用行上面的代码片段似乎说明了在java中什么是非法的,而不是为什么。如果有人能够用一个例子来解释,那对我来说会非常有帮助。 在此先感谢。

+0

IIRC,泛型不是协变的,因为他们无法改变阵列,如何实现/ Java中(向后兼容)的早期版本中使用,它按门铃的人? – Rhangaun 2010-04-18 02:12:33

+0

@Skeptic,Arrays是一个协变泛型实现的例子 - 它会抛出运行时异常。 Java不能这样做,因为泛型在运行时会被擦除,所以它只能通过限制协方差来控制泛型。 – Yishai 2010-04-18 02:31:49

+0

@Yishai,Steele在一个名为“Growing a Language”的演讲中讨论了数组的问题,这个演讲目前我看不到。 – Rhangaun 2010-04-18 02:57:59

回答

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

在Java中,整数数(java.lang.Number)继承,所以直观,任何一个Integer (java.lang.Integer)也就是一个数字,而是什么文章指出的是,与泛型它不会按照这种方式,因为考虑到例如,您最终可能会将浮点数(这是一个数字)放入List<Integer>,这是非法的,因为浮点数不是整数。

结论:泛型不是协变的。

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

+0

谢谢。 8)我认为解释与代码片段无关。傻我。 – soocracy42 2010-04-18 02:27:23

+0

+1用于读取有效的Java。我已经写了很多年的代码,并且在一个月前拿起EJ,并立即学到了5或6个非常重要的策略。 – 2010-04-18 04:14:12

+0

本文也非常有帮助:https://www.ibm.com/developerworks/java/library/j-jtp01255/index.html – 2012-04-03 11:35:12

8

如果你可以做这样的事情:

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

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

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

事情会去非常错误的。在这个例子中,bar是foo的别名,如果你能做到这一点,你会失去类型安全性,这是泛型存在的主要原因。

+0

非常感谢。我不确定别名部分。这证实了我的假设是正确的。 – soocracy42 2010-04-18 02:24:43

+0

啊!所以现在“你好”不仅在'bar'(这可能很好),而且在'foo'中。最后它是有道理的:)我想我可以声明一个列表转换方法,这将不得不复制列表,嗯。 – 2014-08-01 06:38:40

-2
public class vechicle { 
void drive(){ 
} 
} 
class car extends vechicle{ 
     //Covariance 
    vechicle getObject(){ 
     return new car(); 
    } 
     //contravariance 
    car getmyObject(){ 
     return (car) new vechicle(); 
    } 
} 
+0

java.lang.ClassCastException将在'return(car)new vechicle();' – Rembo 2014-03-05 05:00:32