The following code gives me an error for the line l.add
List<? extends Number> l = new ArrayList<Integer>();
l.add(1);
and forces me to write it as l.add(1, null);
Why is it so?
With a wildcard on the variable l
, the compiler doesn't know (or care) which subclass of Number
(or Number
itself) the type parameter really is. It could be an ArrayList<Double>
or an ArrayList<BigInteger>
. It can't guarantee the type safety of what's passed in to add
, and because of type erasure, the JVM can't catch a type mismatch either. So the compiler preserves type safety by disallowing such calls to add
unless the value is null
, which can be any type.
To get add
to compile, you must declare l
as:
List<? super Integer> l = new ArrayList<Integer>();
or you can remove the wildcard:
List<Integer> l = new ArrayList<Integer>();
It has to be:
List<? super Integer> l = new ArrayList<Integer>();
l.add(1);
Note the <? super Integer>
declaration. It's called an upper-bound wildcard.
What does it do?
It restricts the Runtime type of the elements of the ArrayList
to be one of the super classes of Integer
, e.g. Integer
, Number
or Object
, which means that you will be able to assign l
to:
new ArrayList<Integer>
new ArrayList<Number>
new ArrayList<Object>
In the three cases, the statement l.add(1)
is perfectly valid, so there's no compile-time error.
More info:
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