List<? extends MyType>
Asked Answered
B

5

42

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?

Brod answered 27/5, 2009 at 21:10 Comment(1)
If class Bar extends class Foo and class Baz has generic<T> then Baz<Foo> waldo = new Baz<Bar>() will not work because Baz<Bar> is not a subclass of Baz<Foo>, Bar is a subclass of Foo. Sub classing does not apply to generics. ArrayList<Object> flob = new ArrayList<Double>() will not work. Simply put, inheritance does not apply to generics. Since you do List<? extends MyType> you could have List<Some sub type> = new ArrayList<MyType>. Since they aren't the same. no bueno.Oeildeboeuf
M
34

You cannot do a "put" with extends . Look at Generics - Get and Put rule.

Meiny answered 27/5, 2009 at 21:16 Comment(2)
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.Downhill
Point of pedantry: You can put null "with extends". Also you can capture the type and "put" references you've previous "got".Aardvark
A
28

Consider:

class MySubType extends MyType {
}

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

sub now contains a MyType which is very wrong.

Aardvark answered 27/5, 2009 at 21:29 Comment(0)
V
6

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.

Veedis answered 27/5, 2009 at 21:29 Comment(0)
A
3

There is a similar thread here: How can elements be added to a wildcard generic collection?

To get an idea of how generics works check out this example:

    List<SubFoo> sfoo = new ArrayList<SubFoo>();
    List<Foo> foo;
    List<? extends Foo> tmp;

    tmp = sfoo;
    foo = (List<Foo>) tmp;

The thing is, that wasn't designed for local/member variables, but for function signatures, that's why it's so ass-backwards.

Amphetamine answered 23/3, 2011 at 13:16 Comment(0)
C
3

I dont know if this will really help you, but this is something I had to use while calling a generic method of Spring Framework and wanting to return also a generic list:

public <T> List<T> findAll(String tableName,Class<?> table) {
    String sql = "SELECT * FROM "+ tableName ;
    List<?> entities = getSimpleJdbcTemplate().query(sql,
            ParameterizedBeanPropertyRowMapper.newInstance(table));
            return (List<T>) entities;
}

Seems the parametrization needs you to use the ? sign in the list to receive the results and then cast the list to the expected return type.

Iam still dazzled by generics...

Colloid answered 16/3, 2012 at 1:19 Comment(1)
dont create SQL querys by String concatenation- see SQL injectionSassaby

© 2022 - 2024 — McMap. All rights reserved.