У меня есть интерфейс 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)
статически обеспечивает набор B
s, со схемой маркировки значения по умолчанию.
Какое-либо понимание относительно того, почему это? Кажется, что универсальный U и подстановочный знак делают то же самое.
В первой конструкции вы указываете, что возвращаете Список
интерфейса переданного элемента. Вы указываете взаимосвязь между переданными в Object а возвращаемый тип объекта в U расширяет направление T
. В этом случае компилятор может связать A
и B
с T
и U
соответственно.
Во втором случае есть такого различия нет, поэтому компилятор предполагает, что T
ссылается на B
, и вводит возвращаемое значение как List
. Затем вы попадаете в ловушку, где, хотя B
является экземпляром A
, List
не является экземпляром List
.
Компилятор определяет параметр типа для метода listFactory
, отличный от ожидаемого. Он предполагает, что T
является типом B
, поэтому подпись фактически является List listFactory (Collection Extends B> source)
. Укажите параметр типа A
, явно указав его при вызове метода:
List<A> tester = Test.<A> listFactory(B.defaultCollectionFactory(3));