Wildcards & PECS Rule
Wildcards (?) express unknown type parameters. ? extends T means the type is T or a subtype (upper-bounded). ? super T means the type is T or a supertype (lower-bounded). PECS: Producer Extends, Consumer Super.
PECS = 'Producer Extends, Consumer Super.' Think of a fruit bowl: '? extends Fruit' = you can TAKE fruit out (produce/read), but can't put any in (is it an Apple bowl or Orange bowl?). '? super Apple' = you can PUT apples in (consume/write), but what you take out is just 'Object.'
PECS: if a collection produces elements you read from, use ? extends T (covariant — read-only). If it consumes elements you write to, use ? super T (contravariant — write-only). List<? extends Number> lets you read Numbers but not add any type (the compiler doesn't know the exact element type). List<? super Integer> lets you add Integers but you can only read Objects. Unbounded wildcard List<?> is useful when you don't care about the element type (printing, counting). Collections.copy() source uses ? extends T, dest uses ? super T — textbook PECS.
Wildcard capture: when a method receives List<?>, the compiler performs wildcard capture internally to give the unknown type a name — used in helper methods. ? is not a type — it's a syntactic shorthand for an existential type. Type inference (Java 8+ target typing) often makes explicit wildcards unnecessary in many situations (e.g., Stream APIs). Bounded type parameters (T extends Comparable<? super T>) appear in Collections.sort and TreeMap comparisons — the ? super T allows passing a Comparator<Animal> to sort a List<Dog>, which is more flexible than requiring Comparator<Dog>.
PECS (Producer Extends, Consumer Super) guides wildcard choice: use ? extends T to read from a generic collection (you get T or a subtype — safe to read, unsafe to write because you don't know the exact type). Use ? super T to write into it (you know at minimum T can be stored — safe to write, only Object can be safely read). This is why Collections.copy(dst, src) is copy(List<? super T> dst, List<? extends T> src). Prefer bounded wildcards in public APIs to maximize flexibility for callers.
You cannot add anything (except null) to a List<? extends Number> — the compiler cannot verify type safety for the specific unknown subtype, so all adds are rejected at compile time.