Как matt freake pointed out in his answer, существует не так много практической разницы между
public static <T> void copyA(List<? super T> dest, List<? extends T> src) // and
public static <T> void copyB(List< T> dest, List<? extends T> src)
Сниппет ниже содержит exampleShowingThatTheyAreBasicallyEquivalent
.
Причина, по которой авторы решили использовать ? super T
, скорее всего, они хотели подчеркнуть PECS principle: Producer extends
- Consumer super
.
В этом примере первый список - потребитель объектов. Он получает только объекты из другого списка. Поэтому его тип должен быть List<? super T>
.
Однако фрагмент кода ниже, также содержит exampleShowingOneSubtleDifference
.Я вряд ли можно думать о том случае, когда это действительно практически отношение, а просто указать на это: Когда вы обойти вывод типа, и пин-код типа <T>
в один конкретный тип, вы все равно можете передать List<? super T>
в качестве первого аргумента первому методу. Во втором, тип должен точно соответствовать - но это просто то, что говорит метод подписи, так что, может быть, это очевидно ...
import java.util.List;
public class PecsExample
{
public static void exampleShowingOneSubtleDifference()
{
List<? super Number> superNumbers = null;
List<Number> numbers = null;
PecsExample.<Number>copyA(superNumbers, numbers); // Works
//PecsExample.<Number>copyB(superNumbers, numbers); // Does not work
}
public static void exampleShowingThatTheyAreBasicallyEquivalent()
{
List<? super Object> superObjects = null;
List<? super Number> superNumbers = null;
List<? super Integer> superIntegers = null;
List<Object> objects = null;
List<Number> numbers = null;
List<Integer> integers = null;
List<? extends Object> extendsObjects = null;
List<? extends Number> extendsNumbers = null;
List<? extends Integer> extendsIntegers = null;
copyA(objects, objects);
copyA(objects, numbers);
copyA(objects, integers);
copyA(numbers, numbers);
copyA(numbers, integers);
copyA(integers, integers);
copyA(superObjects, objects);
copyA(superObjects, numbers);
copyA(superObjects, integers);
copyA(superNumbers, numbers);
copyA(superNumbers, integers);
copyA(superIntegers, integers);
copyA(objects, extendsObjects);
copyA(objects, extendsNumbers);
copyA(objects, extendsIntegers);
copyA(numbers, extendsNumbers);
copyA(numbers, extendsIntegers);
copyA(integers, extendsIntegers);
copyB(objects, objects);
copyB(objects, numbers);
copyB(objects, integers);
copyB(numbers, numbers);
copyB(numbers, integers);
copyB(integers, integers);
copyB(superObjects, objects);
copyB(superObjects, numbers);
copyB(superObjects, integers);
copyB(superNumbers, numbers);
copyB(superNumbers, integers);
copyB(superIntegers, integers);
copyB(objects, extendsObjects);
copyB(objects, extendsNumbers);
copyB(objects, extendsIntegers);
copyB(numbers, extendsNumbers);
copyB(numbers, extendsIntegers);
copyB(integers, extendsIntegers);
}
public static <T> void copyA(List<? super T> dest, List<? extends T> src)
{
for (int i = 0; i < src.size(); i++)
{
dest.set(i, src.get(i));
}
}
public static <T> void copyB(List<T> dest, List<? extends T> src)
{
for (int i = 0; i < src.size(); i++)
{
dest.set(i, src.get(i));
}
}
}
Найдено большое объяснение здесь: http://stackoverflow.com/questions/4343202/difference-between-super-t-and-extends-t-in-java/4343547 # 4343547 –
@DzmitryPaulenka Спасибо за вашу помощь, но я все еще не уверен в различиях между 'List' и 'List extends T>' в этом случае.Я думаю, что 'List ' работает так же, как 'List extends>'. –
Xin