列表<A> canot可以发送到方法(List <super-class-of-A>) - 为什么不呢?

cor*_*ath 2 java generics

我一定错过了关于Java中泛型的东西,但为什么这不起作用?

List<String> list = new ArrayList<String>();
Run Code Online (Sandbox Code Playgroud)

无法发送至:

method( List<Object> );
Run Code Online (Sandbox Code Playgroud)

但它不起作用?怎么会?

但如果方法是:

method( Object o )
Run Code Online (Sandbox Code Playgroud)

它可以用于:

method( new String("hello") ) 
Run Code Online (Sandbox Code Playgroud)

没有任何问题

q1)String确实扩展了Object,为什么不能传递给它?

List<Object>
Run Code Online (Sandbox Code Playgroud)

q2)为什么会这样

method( List<? extends Object> ) 
Run Code Online (Sandbox Code Playgroud)

工作?有什么不同?

Bom*_*mbe 10

看这个:

List<String> stringList = new ArrayList<String>();
List<Object> objectList = stringList; // if this was allowed…
objectList.add(new Object());
String s = stringList.get(0); // …this would throw a ClassCastException
Run Code Online (Sandbox Code Playgroud)

显然,这不能被允许工作,因为List<String>它将包含一个Object后来,抛弃了泛型旨在给你的所有类型安全.

  • 您可能希望在示例中添加第四行,以明确如何违反generic的编译时安全性:`String s = stringList.get(0); //在运行时抛出ClassCastException (2认同)

Jor*_*orn 7

List<String>List<Object>由于其他答案中提到的原因,它不是您所预期的子类型.但是,您可以像这样定义方法:

method(List<? extends String> list)
Run Code Online (Sandbox Code Playgroud)

这将允许您从列表中获取字符串,但不能放入任何内容.您可以将List<String>或者理论上将任何String子类型的List 传递给方法.您也可以将其定义为

method(List<? super String> list)
Run Code Online (Sandbox Code Playgroud)

这将允许您将字符串放入列表中,但只能从中读取对象.然后你可以传入一个List<String>或一个List<Object>.请注意,在此示例中没有多大意义(因为您不能将String子类化),但它对其他类型层次结构有意义


Sea*_*wen 5

如果method()被定义为这样怎么办?

void method(List<Object> list) {
  list.add(new Long(1));
}
Run Code Online (Sandbox Code Playgroud)

那没关系吗?哎呀,除非你通过了一个清单<String>!

解释直觉很难,但我可以指出List上的get()方法不会出现这样的问题,对吧?由于list只承诺返回一个Object.问题是"设置"或"添加"方法.它需要匹配超类型,而不是子类型.一般来说,限制种类在泛型土地上是双向的.所以它与简单的参数传递不同,其中子类总是正常的.