views:

773

answers:

3

I have a Java question about generics. I declared a generic list:

List<? extends MyType> listOfMyType;

Then in some method I try instantiate and add items to that list:

listOfMyType = new ArrayList<MyType>();
listOfMyType.add(myTypeInstance); 

Where myTypeInstance is just an object of type "MyType"; it won't compile. It says:

The method add(capture#3-of ? extends MyType) in the type List<capture#3-of ? extends MyType> is not applicable for the arguments (MyType)

Any idea?

+8  A: 

You cannot do a "put" with extends . Look at get-put rule for further explanation .

Surya
Perfect! Thank you.
Lancelot
As Josh Bloch says: "Remember PECS: Producer Extends, Consumer Super." Since listOfMyType is a consumer (you are adding to it), `super` is valid and `extends` is not.
Michael Myers
+1  A: 

You shouldn't need to use the wildcard capture syntax in your case, simply declaring

List<MyType> listOfMytype;

should be enough. If you want to know exactly why, the Java Generics Tutorial has more than you would ever want to know about the esoteric craziness of Java Generics. Page 20 addresses your specific case.

As for why add with the wildcard capture does not work, it is because the compiler can't determine exactly what subclass of MyType the list will be in every case, so the compiler emits an error.

Cameron Pope
+3  A: 

Consider:

class MySubType extends MyType {
}

List<MySubType> subtypeList = new ArrayList<MySubType>();
List<? extends MyType> list = subtypeList;
list.add(new MyType());
MySubType sub = list.get(0);

sub now contains a MyType which is very wrong.

Tom Hawtin - tackline