Любопытство дженериков Java

У меня есть интерфейс A, какой класс B реализации.

Следующие работы общего метода

public static <T, U extends T> List<T> listFactory(Collection<U> source) {
    return new ArrayList<T>(source);
}

но

public static <T> List<T> listFactory(Collection<? extends T> source) {
    return new ArrayList<T>(source);
}

не делает (ошибка компиляции, несоответствие типов), когда я направляю вывод в

List<A> tester = listFactory(B.defaultCollectionFactory(3));

defaultCollectionFactory(int count) статически обеспечивает набор Bs, со схемой маркировки значения по умолчанию.

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

5
задан Jeff Axelrod 5 May 2012 в 12:39
поделиться

2 ответа

В первой конструкции вы указываете, что возвращаете Список интерфейса переданного элемента. Вы указываете взаимосвязь между переданными в Object а возвращаемый тип объекта в U расширяет направление T . В этом случае компилятор может связать A и B с T и U соответственно.

Во втором случае есть такого различия нет, поэтому компилятор предполагает, что T ссылается на B , и вводит возвращаемое значение как List . Затем вы попадаете в ловушку, где, хотя B является экземпляром A , List не является экземпляром List .

2
ответ дан 14 December 2019 в 19:19
поделиться

Компилятор определяет параметр типа для метода listFactory , отличный от ожидаемого. Он предполагает, что T является типом B , поэтому подпись фактически является List listFactory (Collection source) . Укажите параметр типа A , явно указав его при вызове метода:

List<A> tester = Test.<A> listFactory(B.defaultCollectionFactory(3));
3
ответ дан 14 December 2019 в 19:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: