泛型子类型和通配符在Collections.copy中的工作原理如何?

时间:2013-09-02 14:36:24

标签: java generics collections

这是Collections复制方法(部分内容):

public static <T> void copy(List<? super T> dst, List<? extends T> src) {
   for (int i = 0; i < src.size(); i++) {
     dst.set(i, src.get(i));
   }
}

有4个样本电话:

List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
List<Integer> ints = Arrays.asList(5, 6);

1. Collections.copy(objs, ints);
2. Collections.<Object>copy(objs, ints);
3. Collections.<Number>copy(objs, ints);
4. Collections.<Integer>copy(objs, ints);

以上呼叫的工作原理是什么?

我们还可以使用几种可能的签名来声明该方法

1. public static <T> void copy(List<T> dst, List<T> src)
2. public static <T> void copy(List<T> dst, List<? extends T> src)
3. public static <T> void copy(List<? super T> dst, List<T> src)
4. public static <T> void copy(List<? super T> dst, List<? extends T> src)

对于上面的示例调用,

  • 其中第一个限制性太强,因为它只允许调用 目的地和来源具有完全相同的类型。的(被理解)

  • 第二个签名仅在type参数为Object

  • 时有效
  • 第三个签名仅在type参数为Integer

  • 时有效
  • 最后一个签名适用于所有三种类型参数 - 即。,Object, 数字和整数。

请解释第二,第三和最后一个签名?

  

其余三个对于使用的呼叫是等效的   隐式类型参数,但显式类型参数不同。

以上陈述的含义是什么?

1 个答案:

答案 0 :(得分:5)

让我们逐一考虑你的每个签名。

1. public static <T> void copy(List<T> dst, List<? extends T> src)

如果在没有显式类型参数的情况下调用此方法,则将类型参数推断为Object,因为您将List<Object>作为第一个参数传递。然后List<? extends Object>可以接受Integer

但是,如果使用显式类型参数Number进行调用,虽然您可以将List<Integer>传递给List<? extends Number>,但List<Object>和{{1}的情况也是如此因为泛型是不变的。

List<Number>

对于隐式类型参数,2. public static <T> void copy(List<? super T> dst, List<T> src) 将被推断为T,因为您将Integer作为第二个参数传递给List<Integer>。然后List<T>List<Object>的有效替代。

如果使用显式类型参数List<? super Integer>调用方法,则可以将Number作为第一个参数传递,但不能将List<Object>作为第二个参数传递。出于与上述相同的原因。

List<Integer>

现在,此方法签名适用于任何类型。对于推断的任何类型参数,3. public static <T> void copy(List<? super T> dst, List<? extends T> src) dst实例的使用者,而Tsrc实例的生成者。例如,如果使用显式类型参数T进行调用,则Number可以转换为List<Object>,类似地,List<? super Number>可以转换为List<Integer>。因此,两个参数都是有效替换。

因此,在所有3种情况下,如果您没有明确提供类型参数,编译器可以正确推断类型参数。但你应该在这里使用第四个签名 -

  • List<? extends Number>dst个实例的使用者,所以它应该使用下限,
  • Tsrc实例的 producer ,所以它应该使用上限。

相关文章:

<强>参考: