Generics, method signatures, assignments

I thought I understood this, but obviously not ...

I have a method signature like this:

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

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

but if I try and call

doSomething(getTypeBTypeAs());

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

however, if I change sig from doSomething to

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

it still doesn't work but

void doSomething(List typeAs){...}

obviously, it works like a bypass of generics.

which seems odd.

Can anyone fill me up?

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

thanks.

+2
source share
2 answers

The generic TypeA<TypeB> class TypeA<TypeB> is another type from TypeA . You cannot pass a parameter of type TypeA<TypeB> where the method expects TypeA . In addition, TypeA<TypeB> is different from TypeA<TypeC> , so the same restrictions apply.

A classic example (from Effective Java, 2nd ed. AFAIR): 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); 

he will accept both lions and butterflies. However this function

 void func(Container<Animal> animalContainer); 

will not accept a Container<Lion> nor a Container<Butterfly> . Understand that a strong cage, useful for saving lions, would not prevent the butterflies from flying away, and vice versa, a thick but light network to hold the butterflies would not leave a chance against the lion.

If you are really sure that any animal container is right for you, declare your function as follows:

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

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

 void doSomething(List<?> list); 
+4
source

Try the following:

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

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

0
source

All Articles