我有一个接口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和通配符正在做同样的事情。
答案 0 :(得分:3)
编译器推断listFactory
方法的不同类型参数比您预期的要多。它推断T
是B
类型,因此签名实际上是List<B> listFactory(Collection<? extends B> source)
。通过在方法调用中显式指定类型参数A
:
List<A> tester = Test.<A> listFactory(B.defaultCollectionFactory(3));
答案 1 :(得分:2)
在第一个构造中,您指定要返回传入的项的接口的List
。您在{{中指定传入的Object和返回的Object类型之间的关系。 1个方向。在这种情况下,编译器可以将U extends T
和A
分别与B
和T
相关联。
在第二个中,没有这样的区别,因此编译器假定U
引用T
并将返回值键入B
。然后,您陷入陷阱,虽然List<B>
是B
的实例,但A
不是List<B>
的实例。编译器会抱怨:
类型不匹配:无法从List&lt; B&gt;转换列出&lt; A&gt;
您会发现,使用第一个构造,您可以自由地指定List<A>
实现的任何接口的List
或B
层次结构中的任何超类({{1}例如),编译器不会抱怨。