Почему ListDataModel не работает с параметром ограниченного типа? - PullRequest
5 голосов
/ 29 августа 2011

Я только что попытался создать ListDataModel с ограниченным типом, например:

DataModel<? extends Foo> model = new ListDataModel<? extends Foo>(fooList);

, где fooList имеет тип List<? extends Foo>.Я получаю следующую ошибку:

unexpected type
  required: class or interface without bounds
  found: ? extends Foo

Мой текущий способ - скопировать мои данные в ArrayList<Foo> и построить из него DataModel<Foo>, но я хотел бы знать, почему это необходимо, иесть ли способ заставить его работать?

Ответы [ 2 ]

5 голосов
/ 29 августа 2011

<? extends Foo> означает «некоторый тип, я не знаю, какой, который является или расширяет Foo».При построении модели данных вам нужно сообщить ему, какой тип данных он содержит, а не только один неизвестный тип.

Просто создайте свою модель данных следующим образом:

DataModel<? extends Foo> model = new ListDataModel<Foo>(fooList);

К сожалению,Конструктор ListDataModel<Foo> принимает только List<Foo>, а не List<? extends Foo>.Это кажется мне заблуждением.Например, конструктор HashSet<E> принимает в качестве аргумента Collection<? extends E>.Если вы принимаете предупреждение о безопасности типа, просто приведите ваш список к List<Foo>.

1 голос
/ 30 августа 2011

Поскольку ListDataModel только для чтения, его конструктор не может принимать только List<E>.Можно обойтись без этой ошибки проектирования.

Более общий вопрос: предположим, что ListDataModel доступен для записи, что теперь?

Если fooList - это List<? extends Foo>, то это, безусловно,List<W> для бетона W, который расширяется Foo.Тогда мы должны иметь возможность new ListDataModel<W>(fooList), тип результата - DataModel<W>, который можно назначить на DataModel<? extends Foo> model.

Так компилятор внутренне рассуждает о подстановочных знаках (захват подстановочных знаков);Жаль, что мы не можем получить прямой доступ к W в Java (это так называемый недетонируемый тип), но мы можем вызвать захват подстановочного знака посредством вызова метода:

static <W> ListDataModel<W> make(List<W> list)
{
    return new ListDataModel<W>(list);
}

List<? extends Foo> fooList = ...;
DataModel<? extends Foo> model = make( fooList );

При компиляции make( fooList ), компиляторвнутренне уточняет тип fooList до List<W>, где <W extends Foo>;затем все остальное работает естественным образом.

В Java 7 вывод типов распространяется на конструкторы с <> синтаксисом

List<? extends Foo> fooList = ...;
DataModel<? extends Foo> model = new ListDataModel<>(fooList); // OK in Java 7

С <> вызов конструктора во многом аналогичен методузвонки;так что make() больше не нужен.До Java 7 требовались статические фабричные методы, такие как make(), чтобы исправить проблему, заключающуюся в том, что конструкторы не делают вывод.Эта практика устарела.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...