Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java generics: List<Container<?>> = new LinkedList<Container<Double>>() is prohibited?

Tags:

java

generics

How come, in Java, I can write

List<?> list = new LinkedList<Double>();

but not

List<Container<?>> list = new LinkedList<Container<Double>>();

where Container is just something like

public class Container<T> { ... }

This came up because I have a method that accepts a List<Container<?>>, and I would like to use Arrays.asList to pass arguments to it:

process(Arrays.asList(new Container<Double>(), new Container<Double>()));

But the language doesn't allow this, because it infers the type of Arrays.asList to be List<Container<Double>>, and that is not assignable to List<Container<?>>.

If I add a String-parameterized Container to the call,

process(Arrays.asList(new Container<Double>(), new Container<String>()));

it still doesn't work, because it infers the type List<Container<? extends Serializable & Comparable<?>>> for Arrays.asList. Only if I pass in something that is neither Comparable nor Serializable does it work properly.

Of course, I can put in a cast and get the compiler to shut up, but I'm wondering if I'm doing something wrong here.

like image 832
avalys Avatar asked Jan 13 '09 18:01

avalys


3 Answers

Each parameterization must be wildcarded:

List<? extends Container<?>> list = new LinkedList<Container<Double>>();

Edit: I was searching through Angelika Langer's FAQ for an explanation, but didn't find one (it's probably there, but hiding somewhere in the 500 pages).

The way to think about this is that each parameterization is independent, and the compiler will not infer information about the parameterization unless you explicitly say to do so.

like image 54
kdgregory Avatar answered Nov 13 '22 06:11

kdgregory


Edit: I was searching through Angelika Langer's FAQ for an explanation, but didn't find one (it's probably there, but hiding somewhere in the 500 pages).

Thank you very much for the answer. I found an explanation in the FAQ, and after some squinting at it I think I get it.

http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#What%20do%20multilevel%20wildcards%20mean?

like image 29
avalys Avatar answered Nov 13 '22 06:11

avalys


Consider what would happen if you could.

List<Container<Double>> list1 = new LinkedList<Container<Double>>();
List<Container<?>> list2 = list1; // this shouldn't be allowed, because of the below
Container<String> foo = new Container<String>();
foo.add("hi");
list2.add(foo); // legal, because Container<String> is a subtype of Container<?>
Container<Double> bar = list1.get(0);
Double x = bar.get(0); // type error; it is actually a String object
                       // this indicates that type safety was violated

However, using List<? extends Container<?>> doesn't have this problem because you cannot put anything (except null) into a list of this type (because there is no type that is guaranteed to be a subtype of "? extends Container<?>").

like image 32
newacct Avatar answered Nov 13 '22 07:11

newacct