6

我对此方法有疑问java.util.Collections

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

我了解如何<? super T>工作,但是,我不明白为什么第一个参数是List<? super T>而不是List<T>. 我认为在这种情况下它是没有用的。
使用List<T>应该也可以,不是吗?
如果可能的话,你能给我一些例子来理解它吗?

谢谢。

4

2 回答 2

5

不,这是有道理的。例如,考虑这种情况:

  • TInputStream
  • dest是一个List<Object>
  • src是一个List<FileInputStream>

这绝对没问题。当然,您可以在这种情况下进行T或在这种情况下进行 - 但假设您是Object具有以下签名的方法调用它:FileInputStream

public void doSomething(List<? super InputStream> streams) {
    // I want to use copy in here for some reason
}

你不知道它是一个List<InputStream>- 只是它是一个List<? super InputStream>. 如果in中的dest参数只是,我们会被卡住......但是按照它编写方式,我们很好。copy List<T>

就我们对目标列表的要求而言,这也是有意义的——我们需要能够在T其中设置值。同样,我们对源列表的所有要求就是我们可以从中获取值T<? super T><? extends T>很好地表达这些要求。

于 2013-02-13T14:51:46.363 回答
0

如果您将其分解为使用列表的原因,则会更加清楚。

当一个方法打算填充一个列表时,您可以将其限制为使用特定类型 T,但通常您可能希望限制较少。

例如,假设您有一个方法populateWithStudents(List<Student> list) 并且您有Student extend Person

这意味着List<Person>即使 Student 扩展了 Person,您也不能使用带有 a 的方法来填充 Student 对象。

因此,另一方面,如果我们想允许我们将其更改为populateWithStudents(List<? super Student> list). 这样,我们就是说,只要我们可以将 Student 放入列表中,无论它是 Student 对象的列表,还是它的任何超类的列表,都是允许的。

这不仅仅是在明显填充时,而且这个例子有助于理解这个概念。

于 2013-02-13T14:53:21.750 回答