import java.util.List;
import java.util.ArrayList;
interface Canine {}
class Dog implements Canine {}
public class Collie extends Dog {
public static void main(String[] args){
List<Dog> d = new ArrayList<Dog>();
List<Collie> c = new ArrayList<Collie>();
d.add(new Collie());
c.add(new Collie());
do1(d); do1(c);
do2(d); do2(c);
}
static void do1(List<? extends Dog> d2){
d2.add(new Collie());
System.out.print(d2.size());
}
static void do2(List<? super Collie> c2){
c2.add(new Collie());
System.out.print(c2.size());
}
}
The answer for this question tell that when a method takes a wildcard generic typ, the collection can be accessed or modified, but not both. (Kathy and Bert)
What does it mean ‘when a method takes a wildcard generic typ, the collection can be accessed or modified, but not both‘ ?
As far as I know,
The method do1 has List<? extends Dog> d2 so d2 only can be accessed but not modified.
The method d2 has List<? super Collie> c2 so c2 can be accessed and modified and there is no compilation error.
That’s a fair first approximation, but not quite correct. More correct would be:
You can only add null to a
Collection<? extends Dog>because its add method takes an argument of? extends Dog. Whenever you invoke a method, you must pass parameters that are of a subtype of the declared parameter type; but for the parameter type? extends Dog, the compiler can only be sure that the argument is of compatible type if the expression isnull. However, you can of course modify the collection by callingclear()orremove(Object).On the other hand, if you read from a
Collection<? super Dog>, its iterator has return type? super Dog. That is, it will return objects that are a subtype of some unknown supertype ofDog. But differently, the Collection could be aCollection<Object>containing only instances ofString. Thereforeso the only thing we know is that instances of Object are returned, i.e. the only type-correct way of iterating such a Collection is
but it is possible to read from a collection, you just don’t know what types of objects you will get.
We can easily generalize that observation to: Given
and
we can only pass null to method parameters with declared type
T, but we can invoke methods with return typeT, and assign the result a variable of typeSomething.On the other hand, for
we can pass any expression of type
Somethingto method parameters with declared typeT, and we can invoke methods with return typeT, but only assign the result to a variable of typeObject.To summarize, the restrictions on the use of wildcard types only depend on the form of the method declarations, not on what the methods do.