Java泛型好奇心

时间:2009-10-03 19:00:12

标签: java generics collections bounded-wildcard

我有一个接口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和通配符正在做同样的事情。

2 个答案:

答案 0 :(得分:3)

编译器推断listFactory方法的不同类型参数比您预期的要多。它推断TB类型,因此签名实际上是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 TA分别与BT相关联。

在第二个中,没有这样的区别,因此编译器假定U引用T并将返回值键入B。然后,您陷入陷阱,虽然List<B>B的实例,但A不是List<B>的实例。编译器会抱怨:

  

类型不匹配:无法从List&lt; B&gt;转换列出&lt; A&gt;

您会发现,使用第一个构造,您可以自由地指定List<A>实现的任何接口的ListB层次结构中的任何超类({{1}例如),编译器不会抱怨。