为什么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
直接,这可以允许T的所有子类型进入列表。 这实际上有点难以理解。 当你声明它时
List extends T> list = ...
这意味着它可以允许T
任何未知子类型进入列表。 但是,根据该声明,我们无法确保哪个是T
的确切子类型。 所以,我们只能在其中添加null
List extends T>
List extends T>
表示可以将任何内容输出到T,因此真正的列表可以是以下任何一种:
-
List
-
List
-
List
- 等等
您可以看到,即使是新的T
也无法安全地添加到这样的集合中,因为它可能是List
,其中T
不能被放入。 因此,此类List不能添加非空条目。
在这种情况下,您可能只需要List
那你为什么要用这个?!
这种逆变对于方法参数或返回非常有用,其中集合将被读取而不是添加到集合中。 这样做的用途可能是创建一个方法来接受任何包含T项或扩展T项的集合。
public static void processList(Collection extends Vector3d> 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)的子类插入列表中。
在你的例子中,你应该使用“超级”