Bounded Type Parameters in Java
Bounded type parameters restrict which types may be used as generic arguments by requiring them to satisfy a class or interface bound. They let generic code safely use members guaranteed by that bound while retaining type safety.
A bounded type parameter is declared with syntax such as `T extends Number`. Here, `T` can be `Number` or any subtype of `Number`, so the generic method can rely on the members available through `Number`.
A bound may name a class, an interface, or multiple interfaces. Java permits one class bound followed by interface bounds, for example `T extends Number & Comparable<T>`. The type argument must satisfy every declared bound.
Bounds are useful when generic code needs more than the operations available on `Object`. Without a bound, the compiler generally only knows that `T` is an `Object`, so code cannot directly call methods introduced by a more specific type.
Bounds can also be used with recursive type relationships, such as `T extends Comparable<T>`. This expresses that the chosen type can be compared with values of the same type and is common in APIs involving ordering.
The `extends` keyword is used for both class and interface bounds in type-parameter declarations. This differs from wildcard bounds such as `List<? extends Number>`, which constrain an unknown type argument rather than declaring a named type variable.
Key points
- `T extends Type` limits `T` to that type or its subtypes.
- A bound gives the compiler access to members guaranteed by the bound.
- A type parameter can have one class bound and additional interface bounds.
- Multiple bounds use `&`, and the class bound must appear first.
- Bounds improve type safety without requiring callers to give up generic type information.
Interview questions
What is a bounded type parameter in Java?
It is a generic type parameter restricted by an upper bound, such as `<T extends Number>`. The argument supplied for `T` must be `Number` or a subtype of it. The bound also tells the compiler which members can safely be used on values of type `T`. This provides stronger compile-time guarantees than an unbounded type parameter.
Why would you use `<T extends Number>` instead of just `<T>`?
An unbounded `T` is not known to have the methods defined by `Number`. With `<T extends Number>`, the compiler knows that every valid `T` is at least a `Number`. That allows code to call methods such as `doubleValue()` directly. The bound therefore enables useful operations while preserving generic type checking.
Can a Java type parameter have multiple bounds?
Yes. A declaration can specify one class bound followed by one or more interface bounds, using `&`. For example, `<T extends Number & Comparable<T>>` requires `T` to satisfy both constraints. The class, if present, must come first because Java permits only one class superclass relationship.
How is a bounded type parameter different from a bounded wildcard?
A bounded type parameter gives a type a name that can be referenced elsewhere in the declaration, such as `<T extends Number>`. A bounded wildcard describes an unknown type within a range, such as `List<? extends Number>`. The type parameter is useful when relationships between multiple occurrences of the same type matter. A wildcard is often useful when the exact type does not need to be named.