为什么generics类型不适用于参数扩展超类?

这是我一直试图找到解决方案的问题。

我们有两个类定义。 其中一个扩展另一个。

class T{} class TT extends T{} 

要求是应该有一个列表保持对象扩展T

  List list = new ArrayList(); 

但是当我尝试将TT对象(几乎不是它的子类)放入列表时,问题就出现了。

  list.add(new TT()); 

编译错误消息

类型List中的方法add(捕获#2-of?extends Cell)不适用于参数(Cell)

您可以创建List list = new ArrayList(); 直接,这可以允许T的所有子类型进入列表。 这实际上有点难以理解。 当你声明它时

 List list = ... 

这意味着它可以允许T任何未知子类型进入列表。 但是,根据该声明,我们无法确保哪个是T的确切子类型。 所以,我们只能在其中添加null

List List表示可以将任何内容输出到T,因此真正的列表可以是以下任何一种:

  • List
  • List
  • List
  • 等等

您可以看到,即使是新的T也无法安全地添加到这样的集合中,因为它可能是List ,其中T不能被放入。 因此,此类List不能添加非空条目。

在这种情况下,您可能只需要List

那你为什么要用这个?!

这种逆变对于方法参数或返回非常有用,其中集合将被读取而不是添加到集合中。 这样做的用途可能是创建一个方法来接受任何包含T项或扩展T项的集合。

 public static void processList(Collection list){ for(Vector3d vector:list){ //do something } } 

此方法可以接受任何扩展Vector3d的对象集合,因此ArrayList是可以接受的。

同样,一种方法可以返回这样的集合。 从一个指定它返回Collection 的方法返回集合中描述了一个用例的示例。

要求是应该有一个列表保持对象扩展T

如果您只想要一个List ,您可以在其中存储从T扩展的任何类的对象,那么只需创建一个如下所示的List

 List list = new ArrayList(); 

您当前创建列表的方式不允许您向其添加除null之外的任何内容。

使用WildCards时,为Java Generics定义了边界规则

  **extends Wildcard Boundary** 

List表示作为类T的实例或T的子类(例如TT)的对象列表。 这意味着Read很好,但是插入会失败,因为你不知道该类是否被Typed为T.

 **super Wildcard Boundary** 

当您知道列表被键入T或超类T时,可以安全地将T的实例或T(eTT)的子类插入列表中。

在你的例子中,你应该使用“超级”