为什么List <string>不是List <object>的子类型?</object> </string>

时间:2012-03-07 17:37:00

标签: java

  

可能重复:
  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必须是超级的字符串的类,它在技术上是。知道我的推理出错了吗?

2 个答案:

答案 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,它基本上表示AB的子类型,当且仅当您可以使用其中包含{{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>的子类型。查找程序片段以证明这是留给读者的练习。