Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics Collections PECS

Tags:

java

I have a question about this method from 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));   
  }   
}

I understand how <? super T> works, however, I don't understand why the first parameter is List<? super T> instead of List<T>. I think it's useless in this situation.
Using List<T> should work as well, shouldn't it?
Could you give me some examples to understand it if possible, please?

Thanks.

like image 976
Álvaro Ruiz Avatar asked Feb 13 '13 14:02

Álvaro Ruiz


1 Answers

No, it makes sense. For example, consider this situation:

  • T is InputStream
  • dest is a List<Object>
  • src is a List<FileInputStream>

That works absolutely fine. Of course, you could make T either Object or FileInputStream in this situation - but imagine you were calling this from a method with a signature of:

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

You don't know it's a List<InputStream> - only that it's a List<? super InputStream>. If the dest parameter in copy were just List<T>, we'd be stuck... but with the way it is written, we're fine.

It also makes sense in terms of what we require from the destination list - we just need to be able to set values of T within it. Likewise all we require of the source list is that we can get values of T from it. <? super T> and <? extends T> express those requirements well.

like image 196
Jon Skeet Avatar answered Oct 21 '22 13:10

Jon Skeet