2

I was reading the superb Java Generics FAQ by Angelika Langer when I read this source code example which I can't understand:

import java.util.List;
import java.util.ArrayList;
import java.lang.Number;
import java.lang.String;
import java.lang.Long;

class X<T extends List<? extends Number>> {
    public void someMethod(T t) {
        t.add(new Long(0L));    // error
        Number n = t.remove(0);
    }
}

I can't understand why the compiler can't infer that "Long extends Number" and match this with "? extends Number" before type erasure, making <? extends Number> completely useless.

I already read the FAQ, so I'm looking for a simpler explanation as well as for alternatives, please.

Thanks in advance

madtyn
  • 1,469
  • 27
  • 55
  • 1
    Your method also accepts `List`. Would it be OK if compiler would allow you to place Long in it? Here you are adding small number, but what if you attempt to add number which is larger than max int? – Pshemo Aug 13 '17 at 10:53
  • 2
    https://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super – shmosel Aug 13 '17 at 11:16
  • 1
    @shmosel That's a great answer, OP definitely read it. – Oleg Aug 13 '17 at 11:35

1 Answers1

2

Suppose someone uses your class this way:

List<Double> list = new ArrayList<>();
X<List<Double>> x = new X<>();
x.someMethod(list);

Now your method will try to add a Long to a List<Double>. That's why the compiler won't allow it.

You cannot add a Long to a List<? extends Number>, since a List<? extends Number> can be assigned a List<Double>, a List<Integer>, etc...

You can change your class declaration to X<T extends List<Number>>, which will solve the compilation error, since to a List<Number> you can always add a Long (or an instance of any other sub-class of Number).

Eran
  • 387,369
  • 54
  • 702
  • 768
  • 1
    Maybe also explain OP what you **can** do with a `? extends Number` list? This was also part of his question. – Oleg Aug 13 '17 at 11:06
  • 1
    Also `X>` doesn't add anything useful in the context of the question. Instead of doing that you can just declare `someMethod(List t)` and not have a generic class. – Oleg Aug 13 '17 at 11:52