Reputation: 3540
My class has a property that is a two dimensinal list of a certain class T
.
It seems that it is logical to create this property as a List<? extends List<T>>
, thus allowing it to be assigned List<ArrayList<T>>
or List<LinkedList<T>
in addition to List<List<T>>
.
It also seems logical that my getter will return a List<List<T>>
, since we don't need to tell Consumers that what this list can be assigned since the consumer will asign the object he gets from the getter to a variable, and not the other way around.
However, my getter refuses to automatically convert List<? extends List<T>>
to List<List<T>>
, throwing an IncompatibleType error. Why can't it be coerced?
Upvotes: 2
Views: 643
Reputation: 7166
@JB-Nizet explained the reason pretty well: it would allow you to add an ArrayList
to a list of LinkedList
-s.
The short answer is, of course, you cannot do that because the compiler will not let you do that ;)
Let me show you another example. You basically cannot add anything to such collections:
List<? extends List<T>> list = new ArrayList<>();
list.add(new LinkedList<T>()); // compile error
list.add(new ArrayList<T>()); // compile error
List<T> sublist = new ArrayList<>();
list.add(sublist); // compile error
If this is what you want, then you can just use whatever list type within your getter and return the wildcard-type:
public List<? extends List<T>> getSomething() {
List<ArrayList<T>> list = new ArrayList<>();
// do something
return list; // List<ArrayList<T>> converts automatically to List<? extends List<T>
}
If you want clients to add stuff to this list but not remove, then you can use the super
keyword:
List<? super ArrayList<T>> list = new ArrayList<>();
list.add(new ArrayList<T>()); // this is fine
On the other hand, if you want to allow both operations, then simply don't use a wildcard:
public List<List<T>> getSomething() {
return new ArrayList<>();'
}
Upvotes: 1