Java:使用超类操作列表

时间:2010-08-11 22:59:11

标签: java inheritance collections

假设我有MyEdgeMyEdgeModified,这样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,但如果我有一个集合,我必须首先构建一个整体'其他列表能够使用它。为什么?难道我做错了什么?这对我来说似乎是错误和愚蠢的。

2 个答案:

答案 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和子类型SList<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?