skip to content

Multiple Bounds

<T extends A & B> allows several bounds, with at most one class and it must come first. Interviewers use it to check you understand that bounds are an intersection, not alternatives.

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

questions

5

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

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

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

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