skip to content

Wildcards

Unbounded, upper- and lower-bounded wildcards, the PECS rule for choosing between them, capture, and the read and write restrictions each imposes. Wildcards are where generics interviews get genuinely discriminating.

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

explore

questions

25

Contrast `<? extends T>` and `<? super T>`: what each allows for reading and writing, and how you decide which to use.

level: juniorimportance: must knowfreq 66%

answer

  1. extends = read/producer; super = write/consumer
  2. extends reads T, can't add
  3. super adds T, reads Object
  4. PECS: Producer Extends, Consumer Super
  5. both read+write → plain T

basics

~20 s

<? extends T> is for reading: you get T's out but can't add. <? super T> is for writing: you can add T's but reads come back only as Object. Read from it → extends; write into it → super.

solid answer

~40 s

The two bounded wildcards are mirror images. `<? extends T>` (upper bound, covariant) means "T or a subtype": you can safely **read** elements as T, but you **cannot add** anything except null, because the exact subtype is unknown. `<? super T>` (lower bound, contravariant) means "T or a supertype": you can safely **write** a T (or subtype) in, but **reads** come back only as Object. The choice follows PECS — Producer Extends, Consumer Super: if the parameter is a source you read from, use extends; if it is a destination you write to, use super; if you do both, use a plain T. This asymmetry exists because Java generics are invariant, and wildcards are the type-safe way to relax that in exactly one direction at a time.

go deeper

for a junior

States the read/write difference: extends to read, super to write, and knows PECS as a phrase.

for a middle

Explains the soundness behind each restriction and applies PECS to method parameters.

for a senior

Designs APIs with the correct wildcard, handles the both-directions case with plain T, and avoids wildcard return types.

for a principal

Relates use-site wildcards to declaration-site variance and reasons about API ergonomics and inference impact across a codebase.

## Why two wildcards exist Java generics are **invariant**: `List<Integer>` is neither a subtype nor a supertype of `List<Number>`. That keeps the type system sound but makes generic method parameters inflexible. **Bounded wildcards** relax invariance safely in one direction: - `<? extends T>` — **upper-bounded**, **covariant**: "some unknown subtype of T (or T itself)." - `<? super T>` — **lower-bounded**, **contravariant**: "some unknown supertype of T (or T itself)." ## Side-by-side behavior | | `List<? extends T>` | `List<? super T>` | |---|---|---| | Element type | unknown **subtype** of T | unknown **supertype** of T | | Read `get()` | returns **T** (safe) | returns **Object** only | | Write `add(x)` | **forbidden** (except null) | **allowed** for T and subtypes | | Role | **producer** (source) | **consumer** (sink) | | Variance | covariant | contravariant | ### Why extends can read but not write ```java List<? extends Number> nums = new ArrayList<Integer>(); Number n = nums.get(0); // OK — every element is at least a Number nums.add(3); // ERROR — list might be List<Integer>, but the value could violate the real subtype; compiler forbids all non-null adds ``` You can read because every element is guaranteed to be a Number. You can't write because the real list might be `List<Integer>` and the compiler can't prove an arbitrary Number fits. ### Why super can write but reads only Object ```java List<? super Integer> sink = new ArrayList<Number>(); sink.add(7); // OK — an Integer fits any supertype-of-Integer slot Object o = sink.get(0); // only Object — element type is an unknown supertype ``` ## How to choose: PECS **Producer Extends, Consumer Super.** - The parameter is a **producer** (you read T out of it) → `<? extends T>`. - The parameter is a **consumer** (you write T into it) → `<? super T>`. - You **both** read and write it as T → use a plain `T` (no wildcard). Mnemonic example — the JDK copy method has one of each: ```java static <T> void copy(List<? super T> dest, List<? extends T> src); // consumer↑ producer↑ ``` ## Common gotchas - You can always add `null` to either, and you can always read into `Object` from either. - Don't use a wildcard on a return type — it leaks into every caller. - `<?>` (unbounded) is the special case `<? extends Object>`: read-only as Object, can't add anything but null. ## One-line decision rule Ask "does my method read T out of this, or put T into it?" Read → `extends`. Put → `super`. Both → exact `T`.

  • Why can't you add elements to a `List<? extends Number>`?
    The actual list could be a `List<Integer>`, `List<Double>`, etc. The compiler doesn't know which, so it cannot guarantee any specific value (other than null) is the right subtype, and forbids adds.
  • If a parameter is both read from and written to as T, which wildcard should you use?
    Neither — use the exact type `T`. Wildcards each sacrifice one direction; only a plain T supports both safe reads and safe writes.

saying these in an interview costs you the question

  • Thinking you can add elements to a `<? extends T>` collection.
  • Thinking you can read T (not Object) from a `<? super T>` collection.
  • Using a wildcard when the method both reads and writes as T (use plain T).
  • Believing `List<? extends Number>` and `List<Number>` are interchangeable.

context

open as a page

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%

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.

open as a page

Why can you read from a List<? extends Number> but not add elements to it (other than null), and what is the inverse rule for List<? super Integer>?

level: middleimportance: must knowfreq 70%

basics

~20 s

With '? extends Number' the exact type is unknown, so the compiler can't be sure a value you add is allowed, but every element is at least a Number so reading is safe. With '? super Integer' the reverse holds: you can add Integers, but reads only give you Object.

open as a page

What does the wildcard `<? super T>` mean in Java generics, and what can you do with such a collection?

level: middleimportance: must knowfreq 70%

basics

~20 s

<? super T> means "T or any of its parent types." You can safely add T (or its subtypes) to such a collection, but when you read from it you only get back Object, because you do not know the exact element type.

open as a page

What does the PECS mnemonic stand for, and how do you decide between `? extends T` and `? super T`?

level: middleimportance: must knowfreq 72%

basics

~10 s

PECS means Producer Extends, Consumer Super. If a structure gives you (produces) values, use ? extends T. If it receives the values you put in (consumes them), use ? super T.

open as a page

Why can you not add elements (other than null) to a List<?>, but you can still read from it?

level: middleimportance: must knowfreq 62%

basics

~20 s

The compiler doesn't know the real element type behind ?, so it can't be sure any value you add fits - except null, which fits every type. Reading is fine because whatever comes out is at least an Object.

open as a page

What does the unbounded wildcard List<?> mean, and how is it different from List<Object> and the raw type List?

level: middleimportance: must knowfreq 70%

basics

~20 s

List<?> means 'a list of some unknown but specific type'. List<Object> is a list that explicitly holds any object, and raw List has no type info at all. List<?> is type-safe; raw List is not.

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

Why can't you add elements (other than null) to a `List<? extends Number>`?

level: juniorimportance: should knowfreq 58%

basics

~20 s

Because 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.

open as a page

Is List<?> just a fancy way of writing the raw type List? Explain the practical difference.

level: juniorimportance: should knowfreq 40%

basics

~20 s

No. The raw List turns off generic checking and lets you do unsafe things with warnings. List<?> keeps the type checks on: you read as Object and can only add null, so the compiler still protects you.

open as a page

What is the difference between List<?>, the raw type List, and List<Object>, especially regarding type safety and what you can put in them?

level: middleimportance: should knowfreq 50%

basics

~20 s

List<?> is a list of some unknown type and is type-safe — you can't add anything but null. Raw List has no type checking and lets you add anything (unsafe, legacy). List<Object> is a list that explicitly holds any Object and lets you add anything safely.

open as a page

Why can you only read elements as `Object` from a `List<? super T>`, and what is the underlying type-safety reasoning?

level: middleimportance: should knowfreq 48%

basics

~20 s

Because the list's real element type could be T or any of its parents, the compiler doesn't know the exact type. The only type guaranteed to fit every possibility is Object, so reads come back as Object.

open as a page

When you read from a `List<? super Integer>`, what type do you get back, and why?

level: middleimportance: should knowfreq 50%

basics

~10 s

You get back Object. The list could be a List<Object>, so the only type the compiler can guarantee for every element is Object. You can safely add Integers, but reads come back as Object.

open as a page

How does the capture-helper (capture-conversion) idiom let you implement a method like swap on a List<?>, and why is the helper necessary?

level: seniorimportance: should knowfreq 40%

basics

~20 s

You write a public method taking List<?> and have it call a private generic helper method <T> that takes List<T>. Passing the wildcard list to the helper makes the compiler capture the unknown type as T, so inside the helper you can read and write elements consistently.

open as a page

What is wildcard capture in Java generics, and when does the compiler perform it?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Wildcard capture is when the compiler replaces a '?' with a fresh, made-up type variable so it can reason about it as a single concrete type. It happens when a method takes a wildcard-typed argument and binds it to a real type parameter.

open as a page

Why does `Comparator<? super T>` appear in signatures like `Collections.sort` and `Stream.sorted`, and what flexibility does it give callers?

level: seniorimportance: should knowfreq 40%

basics

~20 s

A comparator that knows how to compare T's supertype can also compare T's, since every T is-a supertype. Accepting Comparator<? super T> lets you reuse one general comparator (e.g. for Animal) to sort a list of a subtype (e.g. Dog).

open as a page

Explain the PECS rule and why a method that copies elements into a destination should declare it as `List<? super T>`.

level: seniorimportance: should knowfreq 62%

basics

~20 s

PECS means "Producer Extends, Consumer Super." Something you read from uses extends; something you write to uses super. A copy destination is written to (a consumer), so it should be List<? super T> to accept T and its subtypes.

open as a page

Apply PECS to design a generic `addAll(Collection<T> src, Collection<T> dst)` and a `max(Collection<T>)` method. What wildcards do you use?

level: seniorimportance: should knowfreq 44%

basics

~20 s

For copying, the source produces so use ? extends T, and the destination consumes so use ? super T. For finding a max, the collection only produces elements to compare, so use ? extends T. Wildcards let the methods accept more caller types.

open as a page

When would you choose List<?> for a method parameter instead of a generic type parameter like <T> List<T>?

level: seniorimportance: should knowfreq 48%

basics

~20 s

Use List<?> when the method only cares that it has a list and never needs to name the element type - for example to check its size or print it. Use a type parameter <T> when the element type must appear in more than one place, like returning an element of that same 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

You see a compile error like 'method set in interface List cannot be applied; required: CAP#1, found: Object'. What does it mean and how do you fix it?

level: seniorimportance: nice to knowfreq 30%

basics

~20 s

It means you tried to write a plain Object into a list whose element type is an unknown captured wildcard (CAP#1). The compiler can't prove the Object is the right type. Fix it by routing through a generic helper method so the unknown type gets a name.

open as a page

When should you use an unbounded wildcard `List<?>` instead of `? extends T` or `? super T`, and what can you do with it?

level: seniorimportance: nice to knowfreq 30%

basics

~20 s

Use List<?> when the method does not care about the element type at all — e.g. it only checks size or clears the list. You can read elements as Object and you cannot add anything except null.

open as a page

At runtime, what does List<?> look like, and how does it relate to type erasure and operations like instanceof?

level: seniorimportance: nice to knowfreq 30%

basics

~10 s

At runtime Java erases generic type information, so List<String> and List<Integer> are both just List. Because of that, the only generic instanceof check Java allows is the unbounded wildcard form: obj instanceof List<?>.

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