Reputation: 1037
Suppose I have MyEdge
and MyEdgeModified
, such that MyEdge
is the superclass and MyEdgeModified
is the subclass. Now, suppose I do this:
List<List<MyEdge>> collectionOfEdgeLists = new LinkedList<List<MyEdge>>();
for(int i = 0; i < someValue; i++) {
List<MyEdgeModified> newList = someMethod();
collectionOfEdgeLists.add(newList); //ruh roh
}
Now, if I do this:
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;
}
Then:
collectionOfEdgeLists.add(convert(newList)); //ok...
Now, the problem I'm seeing here is that I can treat each individual MyEdgeModified
as an Edge
, but if I have a collection I have to first build a whole 'nother list to be able to use it. Why? Am I doing something wrong? This seems wrong and dumb to me.
Upvotes: 0
Views: 483
Reputation: 1504092
Consider this code:
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);
... but you've managed to put a reference to an instance of MyEdge
into a List<MyEdgeModified>
- so you've managed to break type safety.
That's what the rules are there to prevent.
Now what you can do is use wildcards:
List<MyEdgeModified> modifiedList = new List<MyEdgeModified>();
List<? extends MyEdge> edgeList = modifiedList;
At that point, you won't be able to add to edgeList
, but you can take items from it... so all is safe.
Now creating a List<List<? extends MyEdge>>
ends up being trickier again... I can't remember offhand whether it's even allowed...
In general, the best place to look for details of this sort of thing is Angelika Langer's Java Generics FAQ.
Upvotes: 3
Reputation: 83330
This is due to the absence of covariance in Java generics.
Covariance means that for some type T
and subtype S
, List<S>
is a subtype of List<T>
.
This is not the case in Java. For the reasoning, assume that covariance exists and consider the following case:
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?
Upvotes: 2