泛型集合PECS

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>应该也可以工作,对吧?
如果可能的话,能否给我一些例子来帮助我理解呢?

谢谢。

2个回答

5
不,这是有道理的。例如,考虑以下情况:
  • TInputStream
  • dest 是一个 List<Object>
  • src 是一个 List<FileInputStream>
这个完全没问题。当然,你可以在这种情况下将 T 设为 ObjectFileInputStream,但是想象一下,如果你从一个签名为以下内容的方法中调用它:
public void doSomething(List<? super InputStream> streams) {
    // I want to use copy in here for some reason
}

你不知道它是一个 List<InputStream> - 只知道它是一个 List<? super InputStream>。如果 copy 中的 dest 参数仅仅是一个 List<T>,我们就会陷入困境...但是由于它的写法,我们没问题了。
从目标列表中所需的角度来看,这也是有意义的 - 我们只需要能够在其中设置 T 的值。同样,我们对源列表所需的也仅仅是能够从中获取 T 的值。 <? super T><? extends T> 很好地表达了这些要求。

0

如果你分解一下为什么要使用List,它会更加清晰。

当一个方法想要填充一个列表时,你可以限制它使用特定类型T,但通常你可能想要更少的限制。

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

这意味着你不能使用那个方法来用List<Person>填充它与Student对象,即使Student扩展了Person。

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接