假设我有MyEdge
和MyEdgeModified
,这样MyEdge
是超类,MyEdgeModified
是子类。现在,假设我这样做:
List<List<MyEdge>> collectionOfEdgeLists = new LinkedList<List<MyEdge>>();
for(int i = 0; i < someValue; i++) {
List<MyEdgeModified> newList = someMethod();
collectionOfEdgeLists.add(newList); //ruh roh
}
现在,如果我这样做:
private List<MyEdge> convert(final List<MyEdgeModified> list) {
final List<MyEdge> otherList = new ArrayList<MyEdge>(list.size());
for(Edge edge : list) {
otherList.add(edge);
}
return otherList;
}
然后:
collectionOfEdgeLists.add(convert(newList)); //ok...
现在,我在这里看到的问题是,我可以将每个人MyEdgeModified
视为Edge
,但如果我有一个集合,我必须首先构建一个整体'其他列表能够使用它。为什么?难道我做错了什么?这对我来说似乎是错误和愚蠢的。
答案 0 :(得分:3)
考虑以下代码:
List<MyEdgeModified> modifiedList = new List<MyEdgeModified>();
// This is what you want to do, but which doesn't work
List<MyEdge> edgeList = modifiedList;
// Now this would have to be valid...
edgeList.add(new MyEdge());
// And this should be valid too...
MyEdgeModified modified = modifiedList.get(0);
...但您已设法将MyEdge
的实例引用到List<MyEdgeModified>
中 - 因此您已设法打破类型安全。
这就是要遵守的规则。
现在可以做的是使用通配符:
List<MyEdgeModified> modifiedList = new List<MyEdgeModified>();
List<? extends MyEdge> edgeList = modifiedList;
此时,您将无法添加到edgeList
,但您可以从中获取项目......所以一切都很安全。
现在创建List<List<? extends MyEdge>>
最终会变得更加棘手...我不记得是否允许它......
一般来说,查找此类细节的最佳位置是Angelika Langer's Java Generics FAQ。
答案 1 :(得分:2)
这是由于Java泛型中没有协方差。
协方差表示对于某些类型T
和子类型S
,List<S>
是List<T>
的子类型。
Java中不是这种情况。根据推理,假设存在协方差并考虑以下情况:
List<String> stringList = new ArrayList<String>();
List<Object> oList = stringList; // Just referring to a subtype as its supertype
oList.add(new Object()); // nothing wrong with adding an Object to a List<Object>
for (String s : stringList) { ... } // now what?