正如matt freake在他的回答中指出的那样,实际上这两者之间没有太大实际区别。
public static <T> void copyA(List<? super T> dest, List<? extends T> src)
public static <T> void copyB(List< T> dest, List<? extends T> src)
下面的代码段包含一个
exampleShowingThatTheyAreBasicallyEquivalent
。
作者选择使用
? super T
的原因很可能是他们想强调
PECS原则:生产者extends
- 消费者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);
}
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));
}
}
}
List<T>
和List<? extends T>
之间的区别。我认为List<T>
的工作方式就像List<? extends>
。 - Xin