When would you prefer a bounded type parameter `<T extends Number>` over an upper-bounded wildcard `<? extends Number>`?
answer
- wildcard = anonymous, type param = named
- appears once + read only → wildcard
- appears >1 / must return it → bounded T
- can't relate two ?s; can't return a ?
- capture helper recovers a name for writes
basics
~20 sUse 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.
solid answer
~50 sBoth `<? extends Number>` and `<T extends Number>` express 'a subtype of Number,' but they differ in whether the type has a name. A wildcard is anonymous: each `? extends Number` is potentially a different unknown type, and you can't name it to relate two occurrences or to return it. A bounded type parameter `T` is named, so you can use it in multiple positions — link the parameter type to the return type, tie two parameters to the same type, or capture the element type to write back into the collection. The guideline: if a type variable appears only once in a method signature and you don't need to name it, prefer the wildcard (simpler, more flexible for callers); if it appears more than once or must be referenced (returns, relating arguments, writes), use a bounded type parameter. The wildcard-capture helper pattern bridges the two when needed.
code
java · 13 lines// Wildcard suffices: element type used once, read-only.
static double sum(List<? extends Number> nums) {
double s = 0;
for (Number n : nums) s += n.doubleValue();
return s;
}
// Named type parameter required: the exact type must flow to the RETURN.
static <T> T firstOrNull(List<T> list) {
return list.isEmpty() ? null : list.get(0); // returns T, not just Object/Number
}
// firstOrNull(List.of(1,2,3)) returns Integer, not just Number.go deeper
Knows both forms mean 'subtype of Number' but may not articulate when to pick which.
States that a named type parameter is needed to return or relate types, and a wildcard suffices for a single read-only use.
Applies the 'appears once → wildcard, else type parameter' rule, explains the anonymity of ?, and knows the capture-helper pattern.
Designs APIs balancing caller flexibility vs expressiveness, mixes named T with producer/consumer wildcards (as in Collections.max), and reasons about inference and capture across overloads.
## Two ways to say 'a subtype of Number' Java gives you two related tools with an upper bound: 1. **Upper-bounded wildcard:** `void m(List<? extends Number> list)` — the element type is anonymous/unknown. 2. **Bounded type parameter:** `<T extends Number> void m(List<T> list)` — the element type has a name, `T`. The word `extends` means the same thing in both (the upper bound). The difference is **naming**. ## Why naming matters A wildcard `?` is anonymous. Two different `? extends Number` occurrences are **not** known to be the same type. So you cannot: - **Return the element type by name.** `Number first(List<? extends Number> l)` can only return `Number`, not the caller's actual subtype. With `<T extends Number> T first(List<T> l)`, calling it on a `List<Integer>` returns `Integer` — the precise type is preserved. - **Relate two parameters.** To say two lists have the *same* element type, you need one name: `<T> void merge(List<T> a, List<T> b)`. Two wildcards `List<? extends Number>, List<? extends Number>` could be different subtypes. - **Write captured elements back.** Inside a wildcard method you can't `set` a read value back (the capture problem). A named `T` makes writes type-check. ## The decision rule (from *Effective Java*) > If a type parameter appears only **once** in a method declaration and you don't need to refer to it, replace it with a wildcard. If it appears **more than once** or must be named, use a bounded type parameter. Wildcards are preferred for API *parameters* you only read, because they impose fewer constraints on callers and keep the signature simpler. Named type parameters are needed when the type flows through (in→out) or links multiple positions. ## Examples side by side ```java // Wildcard: read-only, type used once, no need to name it static double sum(List<? extends Number> nums) { double s = 0; for (Number n : nums) s += n.doubleValue(); return s; } // Bounded type parameter: needs to RETURN the exact type static <T extends Comparable<? super T>> T max(List<? extends T> list) { Iterator<? extends T> it = list.iterator(); T result = it.next(); while (it.hasNext()) { T t = it.next(); if (t.compareTo(result) > 0) result = t; } return result; // returns the caller's actual type } ``` Note `Collections.max`'s real signature combines both: a named `T` for the return, a wildcard `? extends T` for the producer parameter, and `Comparable<? super T>` (consumer) for the bound. ## The capture helper pattern Sometimes you have a wildcard method but need a name for the element type internally (e.g. to swap or set). You delegate to a private generic helper that **captures** the wildcard into a named type variable: ```java public 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))); // E is named, so writes type-check } ``` The public API stays clean (`List<?>`), while the helper recovers a name to do the otherwise-illegal write. ## Summary | Need | Use | |---|---| | Read only, type used once | wildcard `<? extends T>` | | Return the exact type | bounded type param `<T extends ...>` | | Relate two parameters to one type | bounded type param | | Write back into the structure | bounded type param (or capture helper) | Prefer wildcards in public read-only parameters for flexibility; reach for a named bounded type parameter the moment the type must be referenced more than once.
- Why can't a wildcard-parameter method return the caller's exact element type?Because `?` is anonymous; the most specific type the method can name for the return is the upper bound (e.g. `Number`), not the caller's concrete subtype.
- How do you perform a `set`/`swap` on a `List<?>` parameter?Delegate to a private generic helper `<E>` that captures the wildcard into a named type variable, so the write type-checks against `E`.
saying these in an interview costs you the question
- Saying they're interchangeable — you can't name a wildcard to return it or relate two of them.
- Always defaulting to type parameters; wildcards are preferred for read-only params.
- Believing `<T extends Number>` and `<? extends Number>` differ in their bound semantics (they don't — only in naming).
- Not knowing the capture-helper pattern for writes through a wildcard.