Wildcards and capture
advanced17 min readLesson 142 of 180
PECS in copy APIs, and wildcard capture: naming the unknown so operations compile.
PECS from Intermediate, applied at API-design depth. A copy API reads from one list and writes to another:
static <T> void copy(List<? extends T> src, List<? super T> dst) {
for (T t : src) dst.add(t);
}
Two wildcards, one inference point: T is fixed from the call site, src
produces Ts, dst consumes them. When a parameter's type is
List<?> without a type variable, you need wildcard capture — a
private helper reifies the unknown:
static void swap(List<?> list, int i, int j) {
swapHelper(list, i, j);
}
private static <E> void swapHelper(List<E> list, int i, int j) {
list.set(i, list.set(j, list.get(i))); // only legal with a real E
}
list.set(...) on a raw List<?> does not compile — the compiler cannot
prove type safety of the unknown; inside the helper, E is a real type and
the same operations are provably safe. Capture is not a trick; it is how you
tell the compiler "the unknown element type is fixed for this call".