tags:

views:

97

answers:

2

I thought I understood this but obviously not...

I have a method signature like so:

void doSomething(List<TypeA> typeAs){...}

List<TypeA<TypeB>> getTypeBTypeAs(){...}

but if I try and call

doSomething(getTypeBTypeAs());

I get a compile error: "the method doSomething(List) in the type ... is not applicable for the arguments (List>)"

however if i change the sig of doSomething to

void doSomething(List<TypeA<?>> typeAs){...}

it still doesn't work, but

void doSomething(List typeAs){...}

obviously it works as i bypass generics.

which seems odd.

Can someone fill me in?

Also, in this case I'd like doSomething to work with any List containing TypeAs of any generic type; undefined, TypeB, TypeC etc.

thanks.

+3  A: 

A generic class TypeA<TypeB> is a different type from TypeA. You can't pass in a parameter of type TypeA<TypeB> where the method expects a TypeA. Also TypeA<TypeB> is a different type from TypeA<TypeC>, so the same constraints apply.

The classic example (from Effective Java, 2nd Ed. AFAIR) is: we have containers for animals (Container<Animal>) and as subclasses of Animal we have Lion and Butterfly. Now, if you have a method

void func(Animal animal);

it will accept both lions and butterflies. However, this function

void func(Container<Animal> animalContainer);

will not accept a Container<Lion>, neither a Container<Butterfly>. Do realize that a strong cage useful for keeping lions safely would not stop butterflies from flying away, and vice versa a thick but light net to hold butterflies would not stand a chance against a lion.

If you really are sure that any kind of animal container suits you, declare your function like this:

void func(Container<? extends Animal> animalContainer);

Back to your case, I guess the only method to accept both List<TypeA> and List<TypeA<TypeB>> would be something like this:

void doSomething(List<?> list);
Péter Török
If Effective Java has a generics example, it must be in the second edition, because I have the first edition sitting on my desk, and it's several years older than Java 5.
R. Bemrose
yes, it's in the second edition. And it's available online, google it (Effective Java Generics)
Bozho
Also, if you did want the second func to accept a Container containing any animal, it would be `void func(Container<? extends Animal> animalContainer);` would it not?
R. Bemrose
then how do i set up a method ie `doSomething` to accept a list containing any incarnation of `List<TypeA>` ?
pstanton
Thanks guys for the comments, I added a link to the book. @R. Bemrose As chance would have it, I added the same solution at the same time :-)
Péter Török
@pstanton Could you specify more exactly what you mean by "any incarnation of `List<TypeA>`" ?
Péter Török
AHHHHHHHHHHHA! so `List<TypeA<TypeB>>` will match `List<? extends TypeA>` .. that's what i didn't understand. I thought that was designed for where `class TypeB extends TypeA` you could assign a `List<TypeB>` to `List<? extends TypeA>`. that's a little misleading, but i guess it works!. thx.
pstanton
@pstanton I added an answer to your previous question. I am afraid that since `TypeA<TypeB>>` is not a `TypeA` (unless `TypeA` is a standard library container), this won't work.
Péter Török
no, that doesn't work, but you've already answered my question... `List<? extends TypeA>` does match `List<TypeA>` as well as `List<TypeA<TypeB>>`, which is all i need. thx.
pstanton
A: 

Try this:

<T> void doSomething(List<TypeA<T>> typeAs) { ... }

Note the <T> at the beginning of the line. That way doSomething accepts every List containing any TypeAs.

stmax
no, it wouldn't allow just `List<TypeA>`
pstanton
you're right, now i understand what you meant with "undefined".
stmax