cod*_*sme 10 java generics extends
这是我一直试图找到解决方案的问题.
我们有两个类定义.其中一个扩展另一个.
class T{}
class TT extends T{}
Run Code Online (Sandbox Code Playgroud)
要求是应该有一个列表保持对象扩展T
List<? extends T> list = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)
但是当我尝试将TT对象(几乎不是它的T的子类)放入列表时,问题就出现了.
list.add(new TT());
Run Code Online (Sandbox Code Playgroud)
编译错误消息
类型List中的方法add(捕获#2-of?extends Cell)不适用于参数(Cell)
Kee*_*san 11
您可以List<T> list = new ArrayList<T>();
直接创建,这可以允许T的所有子类型进入列表.这实际上有点难以理解.当你声明它时
List<? extends T> list = ...
Run Code Online (Sandbox Code Playgroud)
这意味着它可以允许任何未知的子类型T
进入列表.但是,根据该声明,我们无法确保哪个是确切的子类型T
.所以,我们只能加入null
其中
要求是应该有一个列表保持对象扩展T
如果你只想要一个List
可以存储任何类的对象的地方T
,那么只需创建一个List
如下:
List<T> list = new ArrayList<T>();
Run Code Online (Sandbox Code Playgroud)
您当前创建列表的方式不允许您添加除此之外的任何null
内容.
List<? extends T>
表示可以将任何内容输出到T,因此真正的列表可以是以下任何一种:
List<T>
List<T2>
List<TT>
你可以看到,即使是新的T
不能安全地加入到这样一个集合,因为这可能是一个List<T2>
其T
无法投入.因此,此类List不能添加非空条目.
在这种情况下,您可能只是想要 List<T>
这种逆变可能对方法参数或返回有用,其中将读取集合而不是添加集合.这样做的用途可能是创建一个方法来接受任何包含T项或扩展T项的集合.
public static void processList(Collection<? extends Vector3d> list){
for(Vector3d vector:list){
//do something
}
}
Run Code Online (Sandbox Code Playgroud)
此方法可以接受扩展Vector3d的任何对象集合,因此ArrayList<MyExtendedVector3d>
可以接受.
同样,一种方法可以返回这样的集合.从一个指定它返回Collection <ParentType>的方法返回集合<ChildType>中描述了一个用例的示例.