3

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:

enter image description here

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?

norman
  • 5,128
  • 13
  • 44
  • 75
  • 3
    Most of your diagram is incorrect, unless `List -> List` means `V is a subtype of U`. For example `List` is not a subtype of `List` - see for example: http://stackoverflow.com/questions/2745265/is-listdog-a-subclass-of-listanimal-why-arent-javas-generics-implicit – assylias Nov 17 '12 at 22:44

1 Answers1

2

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 :)

PermGenError
  • 45,977
  • 8
  • 87
  • 106
  • So the thing to watch out for is anything that allows an argument to come in that may not be compatible with another that comes in? – norman Nov 18 '12 at 01:33
  • no, the argument will be compatible, if its not you'd get a compile time error, you should watch out for cases like adding an Cat into an dog list which was passed as an parameter. here your argument would accept either dog or cat , as they both extend animal, but you should be careful about adding wrong things inside the method. – PermGenError Nov 18 '12 at 01:40