Добавление элемента внутри подстановочного типа ArrayList

Я пытаюсь добавить элемент в список, где параметр типа списка является подстановочным знаком, расширяющим вопрос.

    ArrayList<? extends Question> id  = new ArrayList<? extends Question>();
    id.add(new Identification("What is my name?","some",Difficulty.EASY));
    map.put("Personal", id);

Где идентификация является подклассом Question. QUestion — это абстрактный класс.

это дает мне эту ошибку

На линии №1 Cannot instantiate the type ArrayList<? extends Question>

И на линии № 2

The method add(capture#2-of ? extends Question) in the type ArrayList<capture#2-of ? extends Question> is not applicable for the arguments (Identification)

Почему он показывает такую ​​​​ошибку? Что вызывает это? И как бы мне это исправить?


person user962206    schedule 22.08.2012    source источник
comment
ArrayList<? extends Question> означает элемент ArrayList некоторого неизвестного типа числа Question. Этой информации недостаточно для создания объекта (какие виды Questions?), и она не позволяет безопасно добавлять Identification. Возможно, вы хотели ArrayList<Identification> или ArrayList<Question>?   -  person obataku    schedule 23.08.2012
comment
@veer Дело в том. Я хотел добавить другой подтип вопроса, такой как множественный выбор и т. д. и т. д. Сам список будет содержать не только список идентификации, но также умножение или другие подтипы вопроса.   -  person user962206    schedule 23.08.2012
comment
... тогда вам нужно ArrayList<Question> :-) Это позволит добавить любые Question в список.   -  person obataku    schedule 23.08.2012
comment
Почему это разрешено? Я думал, что правило наследования не применяется, когда дело доходит до параметров типа?   -  person user962206    schedule 23.08.2012
comment
Это не связано с правилами наследования... применить... к параметрам типа, это связано с тем фактом, что любые MultipleChoice или Identification являются Question.   -  person obataku    schedule 23.08.2012
comment
@veer похоже, что я неправильно понял эту концепцию параметров типа. Таким образом, это означает, что я могу добавить любой подтип вопроса в список массивов.   -  person user962206    schedule 23.08.2012


Ответы (1)


Представьте себе следующий сценарий:

List<MultipleChoiceQuestion> questions = new ArrayList<MultipleChoiceQuestion>();
List<? extends Question> wildcard = questions;
wildcard.add(new FreeResponseQuestion()); // pretend this compiles

MultipleChoiceQuestion q = questions.get(0); // uh oh...

Добавлять что-то в коллекцию с подстановочными знаками опасно, потому что вы не знаете, какие Question она содержит на самом деле. Это может быть FreeResponseQuestion, но может и не быть, а если это не так, то где-то в будущем вы получите ClassCastException. Поскольку добавление чего-либо в коллекцию подстановочных знаков почти всегда завершается ошибкой, они решили превратить исключение времени выполнения в исключение времени компиляции и избавить всех от некоторых проблем.

Почему вы хотите создать ArrayList<? extends Question>? Это было бы почти бесполезно, потому что вы не можете ничего добавить к нему по вышеуказанной причине. Вы почти наверняка захотите полностью опустить подстановочный знак:

List<Question> id = new ArrayList<Question>();
id.add(new Identification(...));
person Jeffrey    schedule 22.08.2012