List <? расширяет MyType> - PullRequest
38 голосов
/ 28 мая 2009

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

List<? extends MyType> listOfMyType;

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

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

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

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

Есть идеи?

Ответы [ 5 ]

30 голосов
/ 28 мая 2009

Вы не можете делать "пут" с помощью удлинителей. Посмотрите на Generics - правило Get and Put .

26 голосов
/ 28 мая 2009

Рассмотрим:

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, что очень неправильно.

4 голосов
/ 28 мая 2009

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

List<MyType> listOfMytype;

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

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

3 голосов
/ 23 марта 2011

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

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

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

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

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

2 голосов
/ 16 марта 2012

Я не знаю, действительно ли это вам поможет, но это то, что мне пришлось использовать при вызове универсального метода 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;
}

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

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

...