1

I came across following image on oracle docs explaining inheritance in the context of generics:

enter image description here

Doubts

  1. I know List<Integer> is not a sub type of List<Number>, but then how exactly List<Number> is a sub type of List<? extends Number>? Is it just how it is done by java designers? Is there any more details to it, possibly low level?
  2. How List<Number> is sub type of List<? extends Number>?
MsA
  • 2,599
  • 3
  • 22
  • 47
  • "but then how exactly `List extends Number>` is a sub type of `List extends Number>`?" That's the same type. – Andy Turner Feb 23 '20 at 07:38
  • `List extends T>` means "everything in the list can be cast to T". `List` means "everything in the list can be cast to T, *and* the list will accept instances of T". Hopefully it's then obvious why a `List` is also a `List extends T>`. – Andy Turner Feb 23 '20 at 07:42
  • 1
    This is subtyping, not inheritance. – Stephen C Feb 23 '20 at 07:42
  • @AndyTurner sorry I incorrectly asked it. I was to ask "how exactly `List` is a sub type of `List extends Number>`?" – MsA Feb 23 '20 at 10:41

2 Answers2

1

but then how exactly List<? extends Number> is a sub type of List<? extends Number>?

They are the same type! Did you mean:

but then how exactly List<? extends Integer> is a sub type of List<? extends Number>?

List<T> means "a list of Ts", whereas List<? extends T> means "a list of some unknown type, but I know it's a subclass of T". In other words, what List<Number> is is "set in stone", whereas List<? extends Number> can be one of many things: List<Integer>, List<Double>, List<Number> and so on. We don't know.

If you have understood this nuance, you shouldn't find the fact that you can't add Integers to a List<? extends Number> surprising. Why? Because the List<? extends Number> could very well be a List<Double>. You can't add Integers to List<Double>, can you?

Now the answer to the question should be clear, List<? extends Integer> could be a list of any subclass of Integer, whereas List<? extends Number> could be a list of any subclass of Number. Since, Integer extends Number, any list of a subclass of Integer must also be a list of a subclass of Number.

But note that a list of Integer is not a list of Number, since you can't add Doubles to a list of Integer, but you can to a list of Number.

How List<Number> is sub type of List<? extends Number>?

This is kind of "by definition" of the <? extends T> syntax. There is no reason not to allow <T> itself. And I do agree extends is misleading here.


Also note that this is not really "inheritance". All the types involved here are really just the same JVM type List, which is also an interface. Inheritance happens between classes. Your wording in the question body - "subtype" - is more appropriate.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • your last two paragraphs is what all I needed! – MsA Feb 23 '20 at 10:55
  • I tried `List extends Number> l5 = new ArrayList(); l5.add((Number) new Integer(5));`. It was giving error. I am guessing, then what we can add to `l5`? – MsA Feb 23 '20 at 11:00
  • @anir You can't add anything. You can only get stuff (`Number`s, to be specific) out of `l5`. This is known as "[Producers Extend, Consumer Super (PECS)](https://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super)". – Sweeper Feb 23 '20 at 11:02
  • What do you mean by we cannot add anything? No value / element can be added to `l5`!!?? But then why and how it makes sense to have such a list? Also I earlier read that we can only add `null` to `List>` but not any element. I just checked we can also add only `null` to `l5`. Again why so & how it makes sense to have such collection. Also does this apply to all `List<#>` where `#` is "? with super or extend"? May be reading PECS link will explain? – MsA Feb 23 '20 at 11:07
  • 1
    @anir It would be useful if you don't intend to add anything to it :) Obviously, you wouldn't do `new List extends Number>()` (it's illegal anyway) because such a list is useless. However, a method could accept such a list as a parameter if it doesn't need to add to the list. This makes the method more flexible as more types of lists are acceptable. More suggested reading in addition to PECS: https://stackoverflow.com/questions/49124391/java-8-comparator-comparing-static-function/49124661#49124661 – Sweeper Feb 23 '20 at 11:20
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/208355/discussion-between-sweeper-and-anir). – Sweeper Feb 23 '20 at 11:22
0

I used to have the same question as you.

It can be understood using set theory:

  1. List<? extends Number> contains List<Number>, List<Byte>, List<Double>, List<Float>, List<Integer>, List<Short>, List<Long>. You can think of List<? extends Number> as a set of 7 elements listed before. When two non-empty sets A and B are equal. It is not wrong to state that A is a subset of B and B is a subset of A.

  2. List<? extends Number> contains List<Number> as its element. Therefore, List<Number> is a sub-type of List<? extends Number>.

Hope this will help!

TDuong
  • 336
  • 3
  • 11