The full picture
// Producer: we only READ from src -> ? extends
// Consumer: we only WRITE to dst -> ? super
static <T> void copy(List<? super T> dst, List<? extends T> src) {
for (T t : src) dst.add(t);
}
List<Integer> ints = List.of(1, 2, 3);
List<Number> nums = new ArrayList<>();
copy(nums, ints); // works: Integer produced, Number consumes
// Why the rules exist:
List<? extends Number> producer = ints;
producer.add(1); // COMPILE ERROR — might be a List<Double>!
Number n = producer.get(0); // fine — whatever it is, it's a Number
List<? super Integer> consumer = nums;
consumer.add(42); // fine — Integer fits any supertype list
Object o = consumer.get(0); // only Object comes back out- Return types should almost never be wildcards — they force every caller to deal with
?. - If a type variable appears once in a signature, prefer a wildcard; if it links two parameters or parameter-and-return, use
<T>. Comparator<? super T>insort()is consumer-super in the wild: aComparator<Object>can sort anything.