Java 为什么列表<;字符串>;不是列表的子类型<;对象>;?

Java 为什么列表<;字符串>;不是列表的子类型<;对象>;?,java,Java,可能重复: 我试图理解这样一个事实:List不是List的子类型 在《高效Java》中,Josh Bloch指出,尽管这看起来可能违反直觉,但它确实有意义。他说的原因是你可以把任何对象放在列表中,但只能把字符串放在列表中。我不确定这如何证明字符串列表不是对象列表的子类型 也许我被子类型这个词弄糊涂了。我认为它的意思是,当S是T的子类型时,S的实例就是T的实例。因此,要使List成为List的子类型,Object必须是一个字符串的超类,从技术上讲,它是这样的。知道我的推理哪里出错了吗 List

可能重复:

我试图理解这样一个事实:
List
不是
List
的子类型

在《高效Java》中,Josh Bloch指出,尽管这看起来可能违反直觉,但它确实有意义。他说的原因是你可以把任何对象放在
列表中,但只能把字符串放在
列表中。我不确定这如何证明字符串列表不是对象列表的子类型

也许我被
子类型
这个词弄糊涂了。我认为它的意思是,当S是T的子类型时,S的实例就是T的实例。因此,要使
List
成为
List
的子类型,Object必须是一个字符串的超类,从技术上讲,它是这样的。知道我的推理哪里出错了吗

List s=new ArrayList();
List<String> s = new ArrayList<String>();
List<Object> o = s;
o.add(new Object());
String first = s.get(0);  // boom
列表o=s; o、 添加(新对象()); String first=s.get(0);//繁荣
这又回到了
A
作为
B
的子类型的含义。它的正式名称是,基本上说,
A
B
的一个子类型,当且仅当您可以使用任何包含
B
类型的有效程序,交换
A
类型的程序时,它仍然是一个有效程序。这样做的效果是,如果您可以在任何可以使用
B
的地方使用
A
,那么
A
就是
B
的一个子类型

因此,在这种情况下,由于这是有效(有效含义为“编译”)程序的一部分:

公共静态无效点(列表x){
x、 添加(新对象());
}
然后,根据Liskov替换原理,如果
List
List
的一个子类型,这也将是有效程序的一部分:

public static void doThing(List<String> y) {
  y.add(new Object());
}
公共静态无效点(列表y){
y、 添加(新对象());
}
但很明显,第二个代码段无法编译。因此,第二个代码段不是有效程序的一部分,因此
List
不是
List
的子类型


同样,另一种情况也不正确:
List
不是
List
的子类型。查找程序片段以证明这一点是留给读者的练习。

我不确定它是否重复。你有链接吗?请发布示例代码。你的意思是:
List=newlinkedlist()
?@为什么?艾尔:书中没有例子来说明这一点?这似乎…很奇怪。我一点也不理解“过于本地化”的投票结果。为什么太本地化了?如果这不是一个复制品,这是一个好问题。@alpian是的,我认为大致相同。这也是一个很好的答案。谢谢你的评论。英雄联盟我不知道为什么这么有趣,但确实如此!Liskov替换原则:如果
A
B
的一个子类型,那么您应该能够在任何可以使用
B
的地方使用
A
。这表明你不能在任何地方都使用
ArrayList
,你可以使用
ArrayList
。答案很好。我知道问题的一部分是我对subtype这个词的混淆,它意味着层次结构。把层次结构放在爪哇中讨论对象和字符串的中间,然后自动地思考继承,这显然不是我们在这里讨论的。谢谢
public static void doThing(List<String> y) {
  y.add(new Object());
}