Pra*_*eek 6 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));
}
}
Run Code Online (Sandbox Code Playgroud)
有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);
Run Code Online (Sandbox Code Playgroud)
以上呼叫如何运作?
我们还可以使用几种可能的签名声明该方法
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)
Run Code Online (Sandbox Code Playgroud)
对于上面的示例调用,
其中第一个限制性太强,因为它只允许在目标和源具有完全相同类型时进行调用.(理解).
第二个签名仅在类型参数为Object时有效
第三个签名仅在类型参数为Integer时有效
最后一个签名适用于所有三个类型参数 - 即Object,Number和Integer.
请解释第二,第三和最后一个签名?
其余三个对于使用隐式类型参数的调用是等效的,但对于显式类型参数则不同.
以上陈述的含义是什么?
让我们逐一考虑你的每一个签名.
1. public static <T> void copy(List<T> dst, List<? extends T> src)
Run Code Online (Sandbox Code Playgroud)
如果在没有显式类型参数的情况下调用此方法,则类型参数将被推断为Object,因为您List<Object>作为第一个参数传递.然后List<? extends Object>可以接受Integer.
但是,如果使用显式类型参数调用Number,虽然可以传递List<Integer>给List<? extends Number>,但是对于List<Object>和List<Number>,因为泛型是不变的.
2. public static <T> void copy(List<? super T> dst, List<T> src)
Run Code Online (Sandbox Code Playgroud)
对于隐式类型参数,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)
Run Code Online (Sandbox Code Playgroud)
现在,此方法签名适用于任何类型.对于推断的任何类型参数,dst是T实例的使用者,而实例的src生产者T.例如,如果使用显式类型参数调用Number,则List<Object>捕获可转换为List<? super Number>,类似地,List<Integer>捕获可转换为List<? extends Number>.所以,两个参数都是有效的替换.
因此,在所有3种情况下,如果您没有明确提供类型参数,编译器可以正确推断类型参数.但你应该在这里使用第4个签名,原因是 -
dst是消费者的T情况下,所以应该用下界,并src是制片人的T情况下,所以应该使用上限.相关文章:
参考: