skip to content

Upper-Bounded Wildcard

<? extends T> gives you covariant reads — everything comes out as at least a T — at the price of not being able to add anything. Producers use this form, which is the first half of PECS.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

What does the upper-bounded wildcard `List<? extends Number>` mean, and what kinds of lists can you assign to it?

level: juniorimportance: must knowfreq 70%

answer

  1. ? extends T = unknown subtype of T
  2. covariant: List<Integer> fits List<? extends Number>
  3. read as T, can't add (only null)
  4. Producer Extends (PECS)

basics

~10 s

List<? extends Number> means a list of some unknown type that is Number or a subtype of Number. You can assign a List<Number>, List<Integer>, or List<Double> to it.

solid answer

~40 s

An upper-bounded wildcard `<? extends T>` says: the type argument is some single unknown type that is T or any subtype of T. So `List<? extends Number>` accepts `List<Number>`, `List<Integer>`, `List<Double>`, etc. This makes generics covariant: `Integer` is a subtype of `Number`, and with the wildcard `List<Integer>` becomes assignable to `List<? extends Number>` even though plain `List<Integer>` and `List<Number>` are otherwise unrelated. The wildcard is useful when you only want to read elements as `Number` from a list whose exact element type you don't care about. The trade-off is that you cannot add elements (except null), because the compiler can't know the exact element type behind the wildcard.

go deeper

for a junior

Knows ? extends Number means "some subtype of Number," and that you can read elements as Number but not add to such a list.

for a middle

Explains it as covariance, connects it to generics invariance, and states that only null can be added and why.

for a senior

Frames it with PECS (Producer Extends), reasons about the type-safety hole that invariance prevents, and chooses the wildcard in API signatures to widen callers.

for a principal

Discusses API design trade-offs (where to place wildcards in a public signature), interaction with type inference and bounded type parameters, and when a bounded type variable beats a wildcard.

## Background: what a generic type is In Java, a *generic type* like `List<E>` is parameterized by a *type argument*. `List<Integer>` is a list whose elements are `Integer`; `List<Number>` is a list whose elements are `Number`. The thing in angle brackets (`Integer`, `Number`) is the type argument. ## The invariance problem Even though `Integer` is a subtype of `Number` (every `Integer` *is a* `Number`), Java generics are **invariant**: `List<Integer>` is **NOT** a subtype of `List<Number>`. You cannot write `List<Number> nums = new ArrayList<Integer>();` — it won't compile. This is deliberate and prevents a hole: if it were allowed, you could do `nums.add(3.14)` (a `Double`, which is a `Number`) into what is really a list of `Integer`, corrupting it. ## What the wildcard `?` is A *wildcard* `?` is an anonymous, unknown type argument. `List<?>` means "a list of some specific but unknown type." An **upper-bounded wildcard** adds a ceiling: `List<? extends Number>` means "a list of some specific but unknown type that is `Number` or a subtype of `Number`." The word `extends` here is reused from inheritance syntax; for interfaces it still reads `extends` (e.g. `? extends Runnable`), never `implements`. ## What it buys you: covariance With the upper bound, the family of types becomes **covariant**: all of `List<Number>`, `List<Integer>`, `List<Double>`, `List<Long>` are subtypes of `List<? extends Number>`. So a method parameter typed `List<? extends Number>` can accept any of them. Covariance means "varies in the same direction as the element subtyping." ## Why you can READ as the bound Behind `List<? extends Number>`, whatever the real element type is, it is guaranteed to be a `Number`. So reading is safe: ```java Number n = list.get(0); // always valid ``` You get out a value typed as the upper bound (`Number`), even though you don't know the exact subtype. ## Why you CANNOT add (read-only for writes) Suppose `list` is `List<? extends Number>`. At runtime it might really be a `List<Integer>` or a `List<Double>`. If you tried `list.add(someInteger)`, the compiler can't prove the real list accepts `Integer` — it might be a `List<Double>`. To stay safe, the compiler rejects **all** `add(x)` calls for any non-null `x`. The single exception is `list.add(null)`, because `null` is a member of every reference type. This is why an upper-bounded wildcard collection is effectively read-only for additions — it acts as a **producer** (a source you read from), not a **consumer** (a sink you write to). ## The PECS mnemonic Joshua Bloch's rule: **PECS = Producer Extends, Consumer Super.** If a parameter only *produces* (you read T out of it), use `<? extends T>`. If it only *consumes* (you write T into it), use `<? super T>` (a lower-bounded wildcard). `<? extends T>` is the producer side. ## Quick contrast table | Declaration | Can read as | Can add | |---|---|---| | `List<Number>` | `Number` | any `Number` | | `List<? extends Number>` | `Number` | only `null` | | `List<?>` | `Object` | only `null` | Upper-bounded wildcards let an API say "give me any list of Numbers and I'll only read from it," maximizing the set of callers that can use the method while keeping it type-safe.

  • Why can't you add an Integer to a `List<? extends Number>`?
    Because the actual list could be a `List<Double>` or `List<Long>`; the compiler can't prove an `Integer` is acceptable, so it rejects all adds except `null`.
  • Can you use `extends` with an interface, e.g. `? extends Comparable`?
    Yes. In wildcard bounds and type-parameter bounds, `extends` is used for both classes and interfaces; `implements` is never used here.

saying these in an interview costs you the question

  • Saying `List<? extends Number>` is the same as `List<Number>` — it isn't; the wildcard one can't accept adds.
  • Thinking you can add an `Integer` to a `List<? extends Number>`.
  • Believing `List<Integer>` is a subtype of `List<Number>` without a wildcard.
  • Using `implements` instead of `extends` for an interface bound.

context

open as a page

Why is a `Collection<? extends T>` effectively read-only for additions, and what is the one value you can still add?

level: middleimportance: must knowfreq 65%

basics

~20 s

Because the real element type behind the wildcard is unknown, the compiler can't guarantee any value you add fits, so it blocks all add calls. The one exception is null, which is valid for every type.

open as a page

Apply PECS: in a method that copies elements from one list to another, which parameter gets `<? extends T>` and why?

level: seniorimportance: should knowfreq 55%

basics

~10 s

The source list (the one you read from) gets <? extends T> because it produces elements. The destination list (the one you write to) gets <? super T> because it consumes them.

open as a page

When would you prefer a bounded type parameter `<T extends Number>` over an upper-bounded wildcard `<? extends Number>`?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Use a named type parameter <T extends Number> when you need to refer to the exact type by name — for example to return it, relate two parameters, or reuse it. Use a wildcard <? extends Number> when the type is used only once and you just read from it.

open as a page

At runtime, how is `List<? extends Number>` represented, and what does that imply for reflection, instanceof, and array creation?

level: principalimportance: nice to knowfreq 25%

basics

~20 s

Generics, including the wildcard, are erased at compile time. At runtime there is just List — the ? extends Number part is gone. So you can't instanceof List<? extends Number> it, and you can't create generic arrays of it.

open as a page