Reputation: 133
In my Android Studio project I have simple structure of classes:
public class P{}
public class A extends P{}
public class B extends P{}
And in another class I have a List:
private List<? extends P> data;
private List<A> listA;
private List<B> listB;
But when I try to do that:
data = listA; //it's ok
data.addAll(listB); //it calls error
The second line is red in Android Studio and error is:
addAll(java.util.Collection<capture<? extends com.mydomain.P>>)
in List cannot be applied to (java.util.List<com.mydomain.subclass.B>)
How can I solve this problem?
Upvotes: 2
Views: 7290
Reputation: 46841
Try this one if you are using ArrayList
only.
public class P {}
public class A extends P {}
public class B extends P {}
public class MyList<T extends P> extends ArrayList<P> {
private static final long serialVersionUID = 1L;
...
}
private static MyList<? extends P> data;
private static MyList<A> listA;
private static MyList<B> listB;
public static void main(String[] args) throws IOException {
data = listA; // it's ok
data.addAll(listB); // it's ok
}
Upvotes: 1
Reputation: 39406
When you declare private List<? extends P> data;
You require a specific type that extends p for the content of your list, which is not necessary. You can simply use:
private List<P> data;
As any class that extends P
(B and A alike) will be accepted.
(That prevent you from assigning data = listA
, though)
Upvotes: 5
Reputation: 280030
When you use a parameterized type like List
, the compiler does some type binding and type checking at compilation time.
So with a variable declared as
List<A> listA;
any use of listA
will be with the type argument A
.
With a variable declared as
List<?> data;
any use of data
will be with the type argument ?
which is the wildcard, but the actual type is unknown.
Given that it doesn't know the actual type, the compiler can't let you make use of it. The add(E)
method of List
depends on the type variable. So
List<A> listA = ...;
listA.add(someA);
would be fine since someA
is of type A
.
Now you may think
List<?> data = listA;
data.add(someA); // theoretically fine
should word, but like this
List<?> data = someMethod();
data.add(someA);
it doesn't. What if the referenced List
isn't meant to hold A
objects?
The compiler simply can't allow this. That is what type-checking all about with generics.
Upvotes: 3