Please give me a hint as to what is going on here:
List<? extends Number> a = new ArrayList<Number>();
List<? extends Number> b = new ArrayList<Number>();
a.addAll(b); // ouch! compiler yells at me, see the block below:
/*
incompatible types
found : java.util.List<capture#714 of ? extends java.lang.Number>
required: java.util.List<java.lang.Number>
*/
This simple code does not compile. I vaguely remember something related to type captures, like those should be mostly used in interface specs, not the actual code, but I never got dumbfounded like that.
This of course might be fixed brute-forcefully, like that:
List<? extends Number> a = new ArrayList<Number>();
List<? extends Number> b = new ArrayList<Number>();
@SuppressWarnings({"unchecked"})
List<Number> aPlain = (List<Number>) a;
@SuppressWarnings({"unchecked"})
List<Number> bPlain = (List<Number>) b;
aPlain.addAll(bPlain);
So, do I really have to either give up captures in the declaration (the capture came to me from an interface, so I'll have to change some API), or stick with type casts with suppression annotations (which generally suck and complicates code a bit)?
The problem is that if you use List<? extends Number>
you could actually do:
List<? extends Number> a = new ArrayList<Integer>();
List<? extends Number> b = new ArrayList<Double>();
a.addAll(b); //ouch, would add Doubles to an Integer list
The compiler can't tell from List<? extends Number>
what the actual type parameter is and thus won't let you do the add operation.
You also shouldn't cast the lists to List<Number>
if you get them as a parameter, since you could actually have a list of Integer objects and add Double objects to it.
In that case you better create a new List<Number>
and add the objects from both lists:
List<Number> c = new ArrayList<Number>(a.size() + b.size());
c.addAll(a);
c.addAll(b);
Edit: in case you create both lists locally, you would not neet the ?
wildcard anyway (since you'd always have List<Number>
).
You have essentially two lists of possibly different types. Because ? extends Number
means a class which extends Number
. So for list a
it can be classA
and for list b
it can be for example classB
. They are not compatible, they can be totally different.
Don't use the ?
wildcard. It means "Some specific type I don't know", and since you don't know the type, you can't add anything to the list. Change your code to use List<Number>
and everything will work.
This is fast becoming the most frequently asked Java question, in a hundred variations...
PECS (producer-extends, consumer-super)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With