Java › Generics
How do bounded wildcards (? extends T and ? super T) work, and what does the PECS (Producer Extends, Consumer Super) mnemonic mean for choosing between them?
AdvancedAnswer
? extends T (an upper-bounded wildcard) means the parameterized type is T or some unknown subtype of T, letting you safely READ elements as T (since whatever the actual type is, it's guaranteed to be a T or subtype) but not safely WRITE to it (since the compiler can't verify what you're adding matches the actual unknown specific subtype); ? super T (a lower-bounded wildcard) means the parameterized type is T or some unknown supertype of T, letting you safely WRITE elements of type T into it (since any supertype of T can safely accept a T) but reads only guarantee an Object -- PECS captures this: use extends when a structure is a PRODUCER you only read from, use super when it's a CONSUMER you only write to.
// PECS in action: copying from a producer (extends) to a consumer (super)
public static <T> void copy(List<? extends T> source, List<? super T> destination) {
for (T item : source) { // safe to READ as T from the producer
destination.add(item); // safe to WRITE T into the consumer
}
}
List<Integer> ints = List.of(1, 2, 3);
List<Number> numbers = new ArrayList<>();
copy(ints, numbers); // works: List<Integer> extends Number-compatible, List<Number> accepts IntegerReal-world example The JDK's own Collections.copy(List<? super T> dest, List<? extends T> src) method signature is a canonical real-world application of PECS, precisely allowing a List<Object> destination to receive elements copied from a List<String> source, a combination that wouldn't be possible without these bounded wildcards given generics' invariance.