skip to content

Bounded Type Parameters

Restricting a type parameter with extends, combining several bounds, and the recursive self-referential form. Bounds are what let a generic method actually call methods on its type parameter.

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

explore

questions

16

What is the syntax for declaring a type parameter with multiple bounds in Java, and what does it mean?

level: juniorimportance: must knowfreq 55%

answer

  1. <T extends A & B & C>
  2. & joins bounds; comma separates parameters
  3. Intersection: subtype of ALL bounds
  4. Combined API available inside the method
  5. extends keyword even for interfaces

basics

~20 s

You write <T extends A & B & C>. It means T must be a subtype of all of A, B, and C at once, so you can call methods from all of them on a T value.

solid answer

~50 s

A multiple bound is written <T extends A & B & C>, joining the bounds with the ampersand (&). It constrains the type argument T to be a subtype of every listed bound simultaneously. Practically, inside the generic code you may treat a T value as if it had the combined API of A, B, and C, calling any method declared by any of them. A caller can only supply a concrete type that genuinely implements/extends all of the bounds. Typically the bounds are interfaces, for example <T extends Comparable<T> & Serializable>, requiring the type to be both comparable and serializable. The '&' separator is intentionally different from the comma used to separate distinct type parameters, so <T extends A, U> declares two parameters while <T extends A & B> declares one parameter with two bounds.

go deeper

for a junior

Can write <T extends A & B>, knows & joins bounds and means 'subtype of all of them', and can name a common example like Comparable & Serializable.

for a middle

Explains the intersection semantics (combined API available inside the method) and why & differs from the comma that separates type parameters.

for a senior

Connects the syntax to real API design — choosing multiple bounds to express 'must be comparable and serializable' in a reusable utility, and anticipates the class-first/interface ordering rule.

for a principal

Frames multiple bounds within the broader type-system idea of intersection types, discusses erasure consequences (which bound becomes the erasure) and how that influences signature/library design.

## What problem this solves Java **generics** let you write code parameterized over a type, e.g. `class Box<T>` where `T` is a placeholder filled in later (`Box<String>`). A **bound** restricts which types `T` may be. A *single* bound looks like `<T extends Number>`, meaning "T must be Number or a subclass." Sometimes one constraint isn't enough: you want T to be, say, both *comparable* (so you can sort it) **and** *serializable* (so you can write it to disk). That is what a **multiple bound** expresses. ## The syntax ```java <T extends A & B & C> ``` - The keyword is always `extends`, even when A/B/C are interfaces (Java reuses `extends` here rather than `implements`). - The bounds are joined by the **ampersand** `&`, not a comma. - The meaning: the actual type argument must be a subtype of **A and B and C all at once** (an intersection of types). ## Why `&` and not `,`? Inside the angle brackets, a **comma separates different type parameters**: ```java class Pair<K, V> { ... } // two parameters K and V <T extends A & B> // ONE parameter T, with two bounds ``` Using `&` keeps the two ideas unambiguous: commas list independent parameters; `&` lists multiple constraints on the *same* parameter. ## What you gain inside the generic code If `T extends Comparable<T> & Serializable`, then a variable of type `T` can be treated as having the **union of all members** of those bounds. You can call `compareTo(...)` (from `Comparable`) on it; the compiler also knows it is `Serializable`, so it can be passed where a `Serializable` is required. The set of usable members is the *combination* of every bound. ```java static <T extends Comparable<T> & java.io.Serializable> T max(T a, T b) { return a.compareTo(b) >= 0 ? a : b; // compareTo allowed; result is also Serializable } ``` ## What the caller must provide The caller can only use this method/class with a concrete type that **really satisfies every bound**. `String` works (it is both `Comparable<String>` and `Serializable`); a type that is comparable but not serializable would be rejected at compile time. ## Key restrictions (covered in sibling questions) - At most **one** of the bounds may be a **class**; the rest must be interfaces. - If a class bound is present, it must be listed **first**. ## First-principles summary Multiple bounds = "AND of constraints" on a single type parameter, written with `&`. They let generic code rely on the combined capabilities of several types while still being type-safe, because only types that honor all the constraints can be plugged in.

  • Inside a method with <T extends Comparable<T> & Serializable>, which methods can you call on a T value?
    Any member declared by Comparable (e.g. compareTo) AND any member of Serializable; the value also satisfies a Serializable requirement. T effectively has the combined API of both bounds.
  • Why does Java use & rather than reusing the comma that separates Pair<K,V>?
    Because the comma already means 'next, independent type parameter'. & disambiguates: it adds another constraint to the SAME parameter rather than declaring a new one.

saying these in an interview costs you the question

  • Using a comma to separate bounds (<T extends A, B>) — that is a syntax error; commas separate type parameters, not bounds.
  • Thinking 'extends' means only classes — for bounds, interfaces also use 'extends'.
  • Believing T must satisfy ANY one bound (OR) — it must satisfy ALL of them (AND/intersection).

context

open as a page

What is an upper bound on a generic type parameter in Java, and why would you use one?

level: juniorimportance: must knowfreq 70%

basics

~20 s

An upper bound uses the extends keyword to say a type parameter must be a given type or a subtype of it, like <T extends Number>. This lets you call that type's methods inside the class or method.

open as a page

In a multiple-bound declaration, what are the rules about including a class bound versus interface bounds, and their ordering?

level: middleimportance: must knowfreq 48%

basics

~20 s

You may have at most one class in the bounds, and if there is one it must come first. All the other bounds must be interfaces, and they go after the class. Multiple classes are not allowed.

open as a page

What does the type bound <T extends Comparable<T>> mean, and why is it written that way?

level: middleimportance: must knowfreq 55%

basics

~20 s

It says T must be a type that can compare itself to other Ts. The bound refers back to T itself, so a value of type T can only be compared with another T, not with unrelated types.

open as a page

What is the difference between a bounded type parameter <T extends Number> and an upper-bounded wildcard <? extends Number>, and when would you choose each?

level: seniorimportance: must knowfreq 55%

basics

~20 s

A bounded type parameter <T extends Number> names a type you can reuse across the signature and return. A wildcard <? extends Number> is an anonymous unknown subtype used for a single parameter; you can read Numbers from it but generally cannot add to it.

open as a page

When a type parameter is declared without an explicit bound (just <T>), what is its bound, and what does that imply for the methods you can call?

level: juniorimportance: should knowfreq 45%

basics

~10 s

Writing <T> is the same as writing <T extends Object>. Because T is only known to be an Object, you can call only Object's methods on it, like equals, hashCode, and toString.

open as a page

Write a generic max method using a recursive bound, and explain why a plain Comparable bound is insufficient.

level: middleimportance: should knowfreq 35%

basics

~10 s

Declare <T extends Comparable<T>> T max(List<T> list) and loop calling compareTo. A plain (raw) Comparable bound takes Object in compareTo, so it can't guarantee you're comparing two Ts and you lose type safety.

open as a page

How do you give a type parameter multiple upper bounds, and what rules govern the order and number of class versus interface bounds?

level: middleimportance: should knowfreq 40%

basics

~20 s

Combine bounds with the & symbol, like <T extends Number & Comparable<T>>. T must satisfy all of them. You can list at most one class, and it must come first; the rest must be interfaces.

open as a page

How does type erasure interact with multiple bounds, and how can reordering interface bounds affect the generated bytecode?

level: seniorimportance: should knowfreq 30%

basics

~20 s

With generics, the compiler removes type info and replaces T with its leftmost bound's type. So in <T extends A & B>, T becomes A. Reordering the bounds can change which type is used as the erasure, which can change casts the compiler inserts.

open as a page

Give a realistic example where a multiple-bound type parameter is the right tool, and explain the design trade-offs versus alternatives.

level: seniorimportance: should knowfreq 34%

basics

~20 s

A generic method that needs an item to be both comparable (to sort/compare) and serializable (to save it) is a good fit: <T extends Comparable<T> & Serializable>. It guarantees both capabilities with one type parameter, checked at compile time.

open as a page

Explain the curiously recurring generic pattern (CRGP) in Java and give a use case for it.

level: seniorimportance: should knowfreq 40%

basics

~20 s

A class declares itself as its own type parameter, like 'class Node<T extends Node<T>>'. Subclasses pass themselves in. It lets base-class methods refer to the actual subclass type — useful for fluent builders that return the right subtype.

open as a page

Why is java.lang.Enum declared as Enum<E extends Enum<E>>?

level: seniorimportance: should knowfreq 30%

basics

~20 s

So each enum is treated as comparable only to its own kind. The recursive bound lets Enum implement Comparable<E> and lets getDeclaringClass return the exact enum type, preventing you from comparing values of two different enums.

open as a page

Why is a recursive (self-referential) upper bound like <T extends Comparable<T>> used, and what does it guarantee?

level: seniorimportance: should knowfreq 35%

basics

~20 s

A bound like <T extends Comparable<T>> says T must be comparable to its own type. It guarantees you can call a.compareTo(b) where both a and b are of type T, so you can safely order values of T.

open as a page

How do multiple bounds combine with recursive (self-referential) type bounds, and why does a pattern like <T extends Enum<T> & SomeInterface> appear?

level: principalimportance: nice to knowfreq 18%

basics

~20 s

A recursive bound mentions T inside its own bound, like <T extends Comparable<T>>, so a type can only be used if it's comparable to itself. You can add more bounds with &, e.g. <T extends Enum<T> & SomeInterface>, to require the enum constant to also implement an interface.

open as a page

When should you reach for a recursive/self-type generic bound in API design, and what are its costs?

level: principalimportance: nice to knowfreq 18%

basics

~20 s

Use a recursive bound when a base type must speak in terms of the concrete subtype — like fluent builder hierarchies or self-comparable types. Costs: noisy signatures leaking the type parameter, an unchecked self-cast, and a subtype contract enforced only by convention.

open as a page

How does type erasure handle an upper-bounded type parameter, and what runtime artifacts (like casts and bridge methods) does it produce?

level: principalimportance: nice to knowfreq 25%

basics

~20 s

At compile time Java erases the type parameter, replacing it with its upper bound (Object if none). The compiler then inserts casts where needed and may generate hidden bridge methods so overriding and polymorphism still work at runtime.

open as a page