Why can't you add elements (other than null) to a `List<? extends Number>`?
answer
- ? extends = unknown single subtype
- compiler can't prove your value fits
- only null is addable
- reads are safe (at least Number)
- prevents heap pollution
basics
~20 sBecause the real list could be a List<Integer>, a List<Double>, or any subtype of Number — the compiler does not know which. It cannot prove your value fits, so it blocks adds. Only null is always safe.
solid answer
~40 s`List<? extends Number>` means "a list of some single unknown subtype of Number." The compiler does not know whether the real list is `List<Integer>`, `List<Double>`, or `List<Number>`. If it let you add a `Double` and the list was actually a `List<Integer>`, you would corrupt it — breaking the very type safety generics exist to guarantee. So adding any typed element is rejected at compile time. The one exception is `null`, which is a valid value of every reference type, so it is always safe. Reading, by contrast, is fine: whatever the element really is, it is guaranteed to be at least a Number. This read-only-for-producers behavior is exactly the "Extends" half of PECS.
code
java · 4 linesList<? extends Number> nums = List.of(1, 2, 3); // really a List<Integer>
Number n = nums.get(0); // OK: read is safe
// nums.add(4); // compile error: cannot prove 4 fits
nums = null; // (reassignment) — and the only addable value is null itselfgo deeper
Explains that the real type is unknown so the compiler blocks adds, and that only null is allowed.
Articulates the heap-pollution scenario and ties the restriction to generic invariance and the producer role.
Reasons about it formally (assignability to the unknown element type) and uses it to justify API parameter choices.
Uses this to frame variance guidance for the team and to evaluate the safety of library signatures and migration risks.
## What the wildcard actually means Write `List<? extends Number>`. The `?` is a **wildcard** — it stands for *one specific but unknown* type. The bound `extends Number` says that unknown type is Number itself or some subtype of Number. So the variable might be bound, at runtime, to a `List<Integer>`, a `List<Double>`, a `List<Number>`, or any other `List<X>` where `X` is a Number. The crucial word is **unknown**. The compiler picks no single type; it must keep the code safe for *every* possibility. ## Why adding is unsafe Suppose adding were allowed: ```java List<Integer> ints = new ArrayList<>(); List<? extends Number> nums = ints; // legal: List<Integer> is a List<? extends Number> nums.add(3.14); // imagine this compiled... Integer i = ints.get(0); // ...ClassCagstException at runtime! ``` If `nums.add(3.14)` compiled, we would have slipped a `Double` into a `List<Integer>`. Later `ints.get(0)` would return what it thinks is an `Integer` and blow up. Generics exist precisely to prevent this kind of *heap pollution*, so the compiler refuses the add up front. More formally: to add a value `v`, the compiler must prove `v` is assignable to the list's element type. But the element type is the unknown `?`. The only value assignable to *every* possible reference type is `null` — so `null` is the lone exception. ## Why reading is still fine Reading has the opposite logic. Whatever the unknown element type is, it is guaranteed to be Number or a subtype, so `Number n = nums.get(0);` is always safe — the result is at least a Number. A `? extends` list is therefore a **producer**: you can take values out but not put them in. ## Connection to PECS This is the "Producer Extends" half of the mnemonic. A `? extends T` collection produces T's (safe to read) and cannot consume them (unsafe to write). The mirror image is `? super T`: safe to write a T, but reads come back as `Object`. ## Terms defined - **Invariance:** `List<Integer>` is not a subtype of `List<Number>` despite `Integer` being a subtype of `Number`. Wildcards exist to work around this when it is safe. - **Heap pollution:** a situation where a variable of a parameterized type refers to an object whose actual element type differs, leading to runtime `ClassCastException`s. - **Bound:** the `extends Number` part that limits which types the `?` can be.
- Is `null` really addable to a `List<? extends Number>`?Yes. `null` is a member of every reference type, so it is the single value the compiler can prove is always safe to add.
- If you need to add real elements, what should the parameter type be instead?Use `List<? super Number>` (or a concrete `List<Number>`/`List<T>`) so the list is a consumer you can safely write into.
saying these in an interview costs you the question
- Thinking you can add any Number subtype because the bound is Number
- Believing the wildcard means "any mix of Number subtypes" (it is one unknown type)
- Saying you cannot read either (reads are fine)
- Forgetting that null is the one allowed add