可能重复:
java generics covariance
我试图理解List<String>
不 List<Object>
的子类型这一事实。
在有效的Java中,Josh Bloch指出,虽然它看似违反直觉,但它确实有意义。他说的原因是你可以在List<Object>
中放置任何对象,但只能在List<String>
中放置String。我不确定这是如何证明String列表不是Object列表的子类型的原因。
也许我对术语subtype
感到困惑。我认为这意味着当S是T的子类型时,S的实例是T的实例。因此,要使List<String>
成为List<Object>
的子类型,Object必须是超级的字符串的类,它在技术上是。知道我的推理出错了吗?
答案 0 :(得分:11)
List<String> s = new ArrayList<String>();
List<Object> o = s;
o.add(new Object());
String first = s.get(0); // boom
答案 1 :(得分:4)
这可以追溯到A
成为B
的子类型的含义。这个的正式名称是Liskov substitution principle,它基本上表示A
是B
的子类型,当且仅当您可以使用其中包含{{1}类型的任何有效程序时1}},交换B
类型的东西,它仍然是一个有效的程序。这样做的结果是,如果您可以使用A
A
,那么B
就是A
的子类型。
所以在这种情况下,因为这是有效(有效意义“编译”)程序的一部分:
B
然后,根据Liskov替换原则,如果public static void doThing(List<Object> x) {
x.add(new Object());
}
是List<String>
的子类型,那么这也将是有效程序的一部分:
List<Object>
但显然第二个片段无法编译。因此,第二个代码段不是有效程序的一部分,因此public static void doThing(List<String> y) {
y.add(new Object());
}
不是List<String>
的子类型。
同样,反过来也不是这样:List<Object>
不是List<Object>
的子类型。查找程序片段以证明这是留给读者的练习。