Почему этот общий код Java с ограниченным подстановочным знаком не компилируется?

Я читал прекрасный FAQ по Java Generics от Анжелики Лангер, когда прочитал этот пример исходного кода. что я не могу понять:

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);
    }
}

Я не могу понять, почему компилятор не может сделать вывод, что «Long extends Number» и сопоставить это с «? extends Number» перед стиранием типа, что делает <? extends Number> совершенно бесполезным.

Я уже прочитал FAQ, поэтому ищу более простое объяснение, а также альтернативы, пожалуйста.

заранее спасибо


person madtyn    schedule 13.08.2017    source источник
comment
Ваш метод также принимает List<Integer>. Было бы нормально, если бы компилятор позволил вам поместить в него Long? Здесь вы добавляете небольшое число, но что, если вы попытаетесь добавить число, превышающее max int?   -  person Pshemo    schedule 13.08.2017
comment
stackoverflow.com/questions/2723397 /   -  person shmosel    schedule 13.08.2017
comment
@shmosel Это отличный ответ, ОП определенно его читал.   -  person Oleg    schedule 13.08.2017


Ответы (1)


Предположим, что кто-то использует ваш класс следующим образом:

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

Теперь ваш метод попытается добавить Long к List<Double>. Поэтому компилятор этого не допустит.

Вы не можете добавить Long к List<? extends Number>, так как List<? extends Number> может быть назначено List<Double>, List<Integer> и т.д...

Вы можете изменить объявление своего класса на X<T extends List<Number>>, что устранит ошибку компиляции, поскольку к List<Number> вы всегда можете добавить Long (или экземпляр любого другого подкласса Number).

person Eran    schedule 13.08.2017
comment
Может быть, также объясните, что вы можете сделать со списком ? extends Number? Это тоже было частью его вопроса. - person Oleg; 13.08.2017
comment
Также X<T extends List<Number>> не добавляет ничего полезного в контексте вопроса. Вместо этого вы можете просто объявить someMethod(List<Number> t) и не иметь общего класса. - person Oleg; 13.08.2017