List <? расширяет MyType>

У меня есть вопрос Java о дженериках. Я объявил общий список:

List<? extends MyType> listOfMyType;

Затем в некотором методе я пытаюсь создать экземпляр и добавить элементы в этот список:

listOfMyType = new ArrayList<MyType>();
listOfMyType.add(myTypeInstance); 

Где myTypeInstance - это просто объект типа MyType; он не будет компилироваться. В нем говорится:

Метод add (capture # 3-of? extends MyType) в типе List < capture # 3-of? extends MyType > не применимо для аргументов (MyType)

Любая идея?

Ответ 2

Рассмотрим:

class MySubType extends MyType {
}

List<MySubType> subtypeList = new ArrayList<MySubType>();
List<? extends MyType> list = subtypeList;
list.add(new MyType());
MySubType sub = subtypeList.get(0);

sub теперь содержит MyType, что очень неправильно.

Ответ 3

Вам не нужно использовать синтаксис захвата подстановки в вашем случае, просто объявив

List<MyType> listOfMytype;

должно быть достаточно. Если вы хотите точно знать, почему в Java Generics Tutorial есть больше, чем вы хотели бы узнать о эзотерическом безумии Java Generics. Страница 20 адресует ваш конкретный случай.

Что касается того, почему добавление с подстановочным знаком не работает, это связано с тем, что компилятор не может точно определить, какой подкласс MyType будет отображаться в каждом случае, поэтому компилятор испускает ошибку.

Ответ 4

Здесь есть аналогичная тема: Как добавить элементы в общую коллекцию подстановочных знаков?

Чтобы узнать, как работают дженерики, посмотрите этот пример:

    List<SubFoo> sfoo = new ArrayList<SubFoo>();
    List<Foo> foo;
    List<? extends Foo> tmp;

    tmp = sfoo;
    foo = (List<Foo>) tmp;

Дело в том, что это не было предназначено для локальных/членных переменных, но для сигнатур функций, почему это так задне-назад.

Ответ 5

Я не знаю, действительно ли это вам поможет, но это то, что мне пришлось использовать, вызывая общий метод Spring Framework и желая вернуть также общий список:

public <T> List<T> findAll(String tableName,Class<?> table) {
    String sql = "SELECT * FROM "+ tableName ;
    List<?> entities = getSimpleJdbcTemplate().query(sql,
            ParameterizedBeanPropertyRowMapper.newInstance(table));
            return (List<T>) entities;
}

Кажется, вам нужно использовать параметризацию? войдите в список, чтобы получить результаты, а затем отнести список к ожидаемому типу возврата.

Я все еще ослеплен дженериками...