Consider the following codes:
class Super {}
class Sub extends Super {}
class Test {
public static void main(String[] args) {
List<? extends Super> list = new ArrayList<Sub>(); //1
list.add(new Sub()); //2
}
}
Line 1 compiles successfully, but line 2 fails compilation:
The method add(capture#2-of ? extends Super) in the type List<capture#2-of ? extends Super> is not applicable for the arguments (Sub)
My questions are:
1) Why does line 1 successfully compile?
2) Is line 1 a good practice in declaring a List (or other collections)?
3) Why does line 2 fail compilation, after list was declared to be type Sub in line 1?
4) Eclipse's autocompletion says only "null" elements are allowed in list now. Why?
Thanks a lot!
1) Why does line 1 successfully compile?
The first line compiles because List<Sub>
is subclass of List<? extends Super>
and that can only be true if List does not allow you to add any new members to it.
?
means that you don't exactly know that it is a List<Sub>
or List<Sub1>
, so it is unsafe to allow adding of new elements into the list and so it does not allow it.
2) Is line 1 a good practice in declaring a List (or other collections)?
If you already know that it is going to be List<Sub>
then I don't find any use, but wildcards are used much when you are passing the List around to other classes like Utilities.
3) Why does line 2 fail compilation, after list was declared to be type Sub in line 1?
Because as I already explained it is unsafe to add any element to list when you dont know the exact type.
4) Eclipse's autocompletion says only "null" elements are allowed in list now. Why?
Because null
is of every reference type, this is why you can assign any object a value of null
.
Always remember PECS (Producer Extends Consumer Super) rule by Josh Bloch when working with generics
Good References:
<? extends T>
as compared to <T>
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