skip to content

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