Java泛型,将一个列表复制到另一个列表

时间:2016-03-09 13:36:09

标签: java list generics

我在java中有这两个函数签名,它应该将列表src复制到列表dst:

1. public static <T> void copy1(List<T> dst, List<? extends T> src)
2. public static <T> void copy2(List<? super T> dst, List<? extends T> src)

问题是两个功能签名之间是否存在差异,以及是否存在第二个选项可行的情况,而第一个选项不起作用。

1 个答案:

答案 0 :(得分:2)

要回答你的第一个问题,这两个函数签名在java中是不同的吗? 的!测试它的最快方法是调用它们copy并验证编译器是否抱怨重复方法。

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

你的第二个问题是,在什么情况下一个人工作而另一个人不会?

基本上我们正在讨论第一个参数dst,因为它是两者之间的唯一区别。

对于任何给定的T,在copy2的情况下,第一个参数必须是T或T本身的超类,第二个参数必须是T或T本身的子类。编译器解释为第一个参数泛型类型必须是T,第二个参数泛型类型只是T的扩展。事实上,如果你尝试,你会看到编译器只采用相同的类型作为第一个参数的通用或它的派生类:

public static <T> void copy2(List<? super T> dst, List<? extends T> src) {
    // Copy
}

public static void main(String[] args) {
    List<Number> dst = new ArrayList<Number>();
    List<Integer> src = getSource();

    copy2(dst, src);  // Works when 2nd generic param type subclass of 1st
    copy2(dst, dst);  // Works when 2nd generic param type same as 1st
    copy2(src, dst);  // Invalid types for method!
}

而在copy1的情况下,第一个参数 T,第二个参数仍然只是T的子类。所以我们在这里讨论相同的场景。在这种情况下,没有一种情况可以发挥作用而另一种情况不会发生。

public static <T> void copy1(List<T> dst, List<? extends T> src) {
    // Copy
}

public static void main(String[] args) {
    List<Number> dst = new ArrayList<Number>();
    List<Integer> src = getSource();

    copy1(dst, src);  // Works when 2nd generic param type subclass of 1st
    copy1(dst, dst);  // Works when 2nd generic param type same as 1st
    copy1(src, dst);  // Invalid types for method!
}