6

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.

Álvaro Ruiz
  • 239
  • 2
  • 8

2 Answers2

5

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.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

If you break it down in why the List is being used it will be a bit more clear.

When a method intends to populate a list, you could restrict it to use a specific type T, however often you might want to be less restrictive.

For example, lets say you have a method populateWithStudents(List<Student> list) And you have Student extend Person

This means that you can't use that method with a List<Person> to fill it with Student objects, even though Student extends Person.

So if on the other hand we would like to allow that we change it to populateWithStudents(List<? super Student> list). This way we're saying that as long as we can fit a Student in the list, no matter if it is a list of Student objects, or a list of any of its superclasses, it is allowed.

This is not just when populating obviously, but this example helps understand the concept.

jbx
  • 21,365
  • 18
  • 90
  • 144