Given the types List<?>
, List<Object>
, List<? super Number>
, List<Number>
, List<Integer>
, and List<? extends Number>
, I am trying to understand their hierarchy.
I know that List<Integer>
is NOT a subtype of List<Number>
, even though Integer
is indeed a subtype of Number
, so I thought that it was instead a subtype of List<? extends Number>
.
But List<? extends Number>
intuitively seems to be a subtype of List<Number>
, which makes List<Integer>
a descendant of List<Number>
after all, as my idea of it shows:
So, if a type is descended from another, but not directly, is it still a subtype of its ancestor (or I am just wrong in the diagram)? This exercise has also gotten me a bit confused about ?
vs. Object
...actually, it looks like I might have List<Object>
and List<? super Number>
mixed up. I guess one of the biggest questions is, "Is 'everything' an Object
...or is everything a ?
?" Or both...or neither?
Reason why List<Integer>
is not a sub type of List<Number>
.
lets just consider a scenario where a List<Number>
accepts List<Integer>
(which would practically wouldn't work).
List<Integer> listI =new ArrayList<Integer>();
List<Double> listD = new ArrayList<Double>();
method(listI);
method(listD);
and you have a method which takes List<Number>
as an argument.
public void method(List<Number> list) {
list.add(new Double()); // would fail if you pass an List<Integer> as Integer is not a super type of Integer.
list.add(new Integer()); //would fail if you pass an List<Double> as Double is not a subtype of Integer
}
so if your method argument declared as List<number>
accepts List<Double>
and you try to add an Integer into the list of Double.which is wrong, because Double is not a super type of Integer thus List<Number>
is not a sub type List<Integer>
.
now consider the same scenario where List<? extends Number>
is a method argument instead of List<Number>
public void method(List<? extends Number> list) {
// list.add(new Double());
// list.add(new Integer());
}
and now you pass an List<Integer>
to this method. if it accepts it and you try to add a Double
to list of Integers. BOOM... you just added a Double to List of Integer .
To give an informal example . consider an Animal supertype with Cat and Dog as subtypes.
now, you have a method which accepts <? extends Animal>
and you pass an Dog to this method. and in the method you try to add an Cat. its adding a wrong type (a CAT) to your Dog, thus **List<Dog>**
is not a subtype of List<? extends Animal>
please let me know if this is not expressive enough.Thanks :)