Reputation: 3267
Here is the problem that I have been being tried to find the solution.
We have two class definitions. One of two extends other one.
class T{}
class TT extends T{}
The requirement is that there should be a list keeps object extends T
List<? extends T> list = new ArrayList<>();
But the problem occures when I try to put a TT object ( barely seems it is a subclass of T )
into the list.
list.add(new TT());
Compilation Error Message
The method add(capture#2-of ? extends Cell) in the type List is not applicable for the arguments (Cell)
Upvotes: 14
Views: 10135
Reputation: 17226
List<? extends T>
indicates that anything can comes out of it can be cast to T, so the true list could be any of the following:
List<T>
List<T2>
List<T3>
You can see that even a new T
cannot safely be added to such a collection because it could be a List<T2>
which T
cannot be put into. As such, such List<? extends T> cannot have non null entries added to them.
In this case you may simply want List<T>
This contravariance can be useful for method parameters or returns, in which a collection will be read, rather than added to. A use for this could be to create a method that accepts any collection that holds items that are T, or extend T.
public static void processList(Collection<? extends Vector3d> list){
for(Vector3d vector:list){
//do something
}
}
This method could accept any collection of objects that extends Vector3d, so ArrayList<MyExtendedVector3d>
would be acceptable.
Equally a method could return such a collection. An example of a use case is described in Returning a Collection<ChildType> from a method that specifies that it returns Collection<ParentType>.
Upvotes: 10
Reputation: 4914
An addition to the other answers posted here, I would simply add that I only use wild cards for method parameters and return types. They're intended for method signatures, not implementations. When I put a wildcard into a variable declaration, I always get into trouble.
Upvotes: 0
Reputation: 213223
The requirement is that there should be a list keeps object extends T
If you just want a List
where you can store objects of any class that extend from T
, then just create a List
like this:
List<T> list = new ArrayList<T>();
The way you've created a list currently, will not allow you to add anything except null
to it.
Upvotes: 7
Reputation: 2136
There are boundary rules defined for Java Generics when using WildCards
**extends Wildcard Boundary**
List means a List of objects that are instances of the class T, or subclasses of T (e.g. TT). This means a Read is fine , but insertion would fail as you dont know whether the class is Typed to T
**super Wildcard Boundary**
When you know that the list is typed to either T, or a superclass of T, it is safe to insert instances of T or subclasses of T (e.g.TT ) into the list.
In your example , you should use "super"
Upvotes: 3
Reputation: 12880
You can create a List<T> list = new ArrayList<T>();
directly, this can allow all subtypes of T into the list. This is actually little difficult to understand. when you declare it as
List<? extends T> list = ...
It means that it can allow any unknown subtypes of T
into the list. But, from that declaration we cannot ensure which is the exact sub-type of T
. so, we can only add null
into it
Upvotes: 11