Search code examples
javagenericstype-parameterbounded-wildcard

Why this Java generic code with bounded wildcard doesn't compile?


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


Solution

  • 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).