Родовые коллекции PECS
У меня есть вопрос об этом методе от 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 ответа
No, it makes sense. For example, consider this situation:
T
являетсяInputStream
dest
этоList<Object>
src
этоList<FileInputStream>
Это работает абсолютно нормально. Of course, you could make T
или Object
или же 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>
, Если dest
параметр в 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
внутри. Likewise all we require of the source list is that we can get values of T
от него. <? super T>
а также <? extends T>
express those requirements well.
Если вы объясните, почему используется Список, это будет немного более понятно.
Когда метод намеревается заполнить список, вы можете ограничить его использованием определенного типа T, однако часто вы можете захотеть быть менее ограничительным.
Например, допустим, у вас есть метод populateWithStudents(List<Student> list)
И у тебя есть Student extend Person
Это означает, что вы не можете использовать этот метод с List<Person>
заполнить его объектами Student, даже если Student расширяет Person.
Так что, с другой стороны, мы бы хотели, чтобы мы изменили его на populateWithStudents(List<? super Student> list)
, Таким образом, мы говорим, что до тех пор, пока мы можем поместить ученика в список, независимо от того, является ли он списком объектов ученика или списком любого из его суперклассов, это разрешено.
Это не только при заполнении, очевидно, но этот пример помогает понять концепцию.