Come matt freake pointed out in his answer, non c'è molta differenza pratica tra
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)
Il frammento di seguito contiene un exampleShowingThatTheyAreBasicallyEquivalent
.
Il motivo per cui gli autori hanno scelto di utilizzare ? super T
è molto probabile che volessero enfatizzare lo PECS principle: Producer extends
- Consumer super
.
In questo esempio, il primo elenco è un utente di oggetti. Riceve solo oggetti dall'altra lista. Pertanto, il suo tipo dovrebbe essere List<? super T>
.
Tuttavia, il frammento di seguito contiene anche un exampleShowingOneSubtleDifference
.Io non può certo pensare di un caso in cui questo è davvero praticamente rilevanti, ma solo per farlo notare: Quando si aggirare l'inferenza di tipo, e il PIN del tipo <T>
a un particolare tipo, è ancora possibile passare in un List<? super T>
come primo argomento del primo metodo. Nella seconda, il tipo deve corrispondere esattamente - ma questo è semplicemente quello che dice la firma del metodo, quindi forse è ovvio ...
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));
}
}
}
Trovato una grande spiegazione qui: http://stackoverflow.com/questions/4343202/difference-between-super-t-and-extends-t-in-java/4343547 # 4343547 –
@DzmitryPaulenka Grazie per il vostro aiuto, ma non sono ancora sicuro delle differenze tra 'Elenco' e 'Elenco extends T>' in questo caso.Penso che 'Lista ' funzioni come 'Elenco extends>'. –
Xin