为什么List 不是List 的子类型?

可能重复:
javagenerics协方差

我试图弄清楚List 不是 List的子类型这一事实。

在有效的Java中,Josh Bloch指出,虽然它看似违反直觉,但它确实有意义。 他说的原因是你可以在List放置任何Object,但只能将String放在List 。 我不确定这是如何certificateString列表不是Object列表的子类型的原因。

也许我对术语subtype感到困惑。 我认为这意味着当S是T的子类型时,S的实例是T的实例。因此,对于ListList的子类型,Object必须是超类字符串,技术上是。 知道我的推理出错了吗?

 List s = new ArrayList(); List o = s; o.add(new Object()); String first = s.get(0); // boom 

这可以追溯到A作为B的子类型的意义。 这个的正式名称是Liskov替换原则 ,它基本上说AB的子类型,当且仅当你可以使用其中有类型B任何有效程序时,交换A类型A东西它仍然会是一个有效的计划。 这样做的结果是,如果你可以在任何可以使用B地方使用B ,那么A就是B的子类型。

所以在这种情况下,因为这是有效(有效意义“编译”)程序的一部分:

 public static void doThing(List x) { x.add(new Object()); } 

然后,通过Liskov替换原则,如果ListList的子类型,那么它也将是有效程序的一部分:

 public static void doThing(List y) { y.add(new Object()); } 

但显然第二个片段无法编译。 因此,第二个片段不是有效程序的一部分,因此List不是List的子类型。

同样,反过来也不是这样: List不是List的子类型。 查找程序片段以certificate这是留给读者的练习。