MA-JAVA0 · Module 18
Wildcards: extends, super, and PECS
Topics: ? extends · ? super · PECS · Read vs write
Overview
Session 18 — Wildcards: extends, super, and PECS
Sometimes a method should accept any list whose elements are at least Number, or any list that can hold at least Integer. Wildcards—? extends T and ? super T—express that flexibility without forcing callers to pick a single concrete type argument. This session teaches variance: what you may read versus write, and the PECS rule (Producer Extends, Consumer Super).
Time: about 90 minutes.
Concepts
1. The problem wildcards solve
Suppose you write:
public static void printAll(List<Object> items) { /* ... */ }
Callers cannot pass List<String>—not a subtype of List<Object> in Java (invariance). Wildcards loosen the type while keeping operations safe.
2. ? extends T — upper bounded wildcard
List<? extends Number> reads as “a list of some unknown type that is a subtype of Number.” You may read Number (or Object) from elements, but you must not add arbitrary numbers—the compiler cannot prove the list is actually List<Integer> vs List<Double>.
public static double sumNumbers(List<? extends Number> nums) {
double total = 0.0;
for (Number n : nums) {
total += n.doubleValue();
}
return total;
}
Here the list is a producer of numbers—you consume numbers from it.
3. ? super T — lower bounded wildcard
List<? super Integer> means “list whose element type is some supertype of Integer,” e.g. List<Number> or List<Object>. You may safely add an Integer, but reading yields only Object unless you narrow carefully—great for sink APIs.
public static void fillInts(List<? super Integer> sink) {
sink.add(1);
sink.add(2);
}
The list is a consumer of integers you produce.
4. PECS
Producer Extends, Consumer Super—coined by Joshua Bloch:
- If your method reads
Telements from a collection parameter, use? extends T. - If your method writes
Telements into a collection parameter, use? super T. - If you both read and write the same
T, prefer a named type parameter<T>on the method instead of a wildcard.
5. Collections.copy mental model
Collections.copy(List<? super T> dest, List<? extends T> src) pairs a consumer destination with a producer source sharing a hidden T.
6. Unbounded ?
List<?> — “list of unknown element type.” You can read elements as Object; you cannot add anything except literal null—rarely what you want except for “I truly only call size()/clear().”
7. Pitfalls
- Trying to
addintoList<? extends Number>—compiler blocks it (exceptnull). - Returning
? extendsfrom APIs without documenting what callers can do—sometimes a named type parameter reads clearer. - Wildcards inside nested generics (
Map<String, ? extends List<Integer>>)—draw the tree on paper before coding.
Examples
Example A — sum with producer wildcard
import java.util.List;
public class Totals {
public static double sumDoubles(List<? extends Number> nums) {
double s = 0.0;
for (Number n : nums) {
s += n.doubleValue();
}
return s;
}
}
Both List<Integer> and List<Double> call sites compile—covariance on read.
Example B — copy integers into a wider sink
import java.util.ArrayList;
import java.util.List;
public class Buffers {
public static void appendDefaults(List<? super Integer> sink) {
sink.add(0);
sink.add(-1);
}
public static void demo() {
List<Number> wide = new ArrayList<>();
appendDefaults(wide); // OK: Number is super of Integer
}
}
If the parameter were List<Integer> only, you could not pass List<Number>—wildcard super fixes that for writes.
Practice check — wildcards and PECS
Multiple-choice check from the Matheion app lesson. Pick an answer for each question, then submit.
1.`List<? extends Number>` is best used when you…
2.`List<? super Integer>` is best used when you…
3.PECS stands for…
4.Why can't you usually `add(new Integer(1))` into `List<? extends Number>`?
5.Reading from `List<? super Integer>` with `get` yields…