How do multiple bounds combine with recursive (self-referential) type bounds, and why does a pattern like <T extends Enum<T> & SomeInterface> appear?
answer
- Recursive bound mentions T in its own bound: Comparable<T>, Enum<T>
- CRTP / curiously recurring generic pattern
- <T extends Enum<T> & Iface> = enum-only AND capability
- Enum is a class → must be leftmost; T erases to Enum
- Self-type enables exact T return and self-typed compareTo
basics
~20 sA 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.
solid answer
~50 sA **recursive (self-referential) bound** refers to the type parameter within its own bound — the classic `<T extends Comparable<T>>` means 'T is comparable to its own kind,' which prevents comparing apples to oranges and lets methods return T rather than a supertype. You can combine this with additional bounds via `&`. The most common real example is constraining enums: `<T extends Enum<T> & SomeInterface>` requires T to be an enum **and** implement `SomeInterface` (e.g. an `EnumSet`-style or strategy API that only accepts enum constants carrying extra behavior). The recursive `Enum<T>` part captures the curiously-recurring-template idiom (CRTP) that Java uses to make enum methods like `compareTo`, `ordinal`, and `getDeclaringClass` self-typed; the `& SomeInterface` part layers on the capability requirement. The class-first/erasure rules still apply: `Enum` is a class so it must be leftmost; T erases to `Enum`. This unlocks APIs that are simultaneously enum-restricted and capability-restricted with full compile-time safety.
go deeper
Not expected to use recursive bounds; can at most recognize <T extends Comparable<T>> as 'comparable to itself'.
Understands <T extends Comparable<T>> enables comparing same-typed values and exact-type returns; may not combine it with extra bounds confidently.
Can read and write <T extends Enum<T> & SomeInterface>, explains the recursive part vs the capability part, and applies the class-first/erasure rules to it.
Explains the CRTP idiom, its self-typing guarantees and limits (enums vs arbitrary classes), JDK precedents like EnumSet's <E extends Enum<E>>, and the API-design trade-offs of such verbose signatures.
## Building blocks We combine two earlier ideas. **Multiple bounds** (`<T extends A & B>`) require T to satisfy several constraints at once. A **recursive (self-referential) bound** is one where the bound *mentions T itself*. The canonical case: ```java <T extends Comparable<T>> ``` Read it as 'T must be comparable **to its own type** T.' This is the **curiously recurring generic pattern** (often called CRTP, borrowed from C++). It exists because `Comparable<X>` is parameterized; without the self-reference you'd allow `Comparable<Object>` and lose precision. With it, `compareTo` takes a `T`, and methods can return `T` (the exact type) instead of a looser supertype. ## Why self-types are useful Consider a generic `max`: ```java static <T extends Comparable<T>> T max(List<T> xs) { ... } ``` The recursive bound guarantees each element can be compared **to other elements of the same type**, and the method can return a `T`, so `max(List<String>)` returns a `String`, not an `Object`. Without recursion you couldn't express 'comparable to itself.' ## Adding more bounds: the enum pattern Now layer a second constraint with `&`. Java's enums are themselves built on a recursive bound: every enum constant's class is `T extends Enum<T>`. So if you want an API that accepts **only enum constants that also implement a given interface**, you write: ```java interface HasCode { int code(); } enum Status implements HasCode { OK { public int code() { return 200; } }, ERROR { public int code() { return 500; } }; } // Accepts only enum types whose constants implement HasCode: static <T extends Enum<T> & HasCode> int codeOf(T value) { // value.ordinal(), value.name() from Enum; value.code() from HasCode return value.code(); } ``` - `Enum<T>` is the **recursive** part: it ties the enum machinery (`ordinal()`, `name()`, `compareTo`, `getDeclaringClass()`) to the exact enum type `T`. - `& HasCode` is the **additional capability** bound. - Together: `codeOf` works only for enums that carry the `HasCode` behavior, with full compile-time checking. This is exactly the shape the JDK uses, e.g. `EnumSet.noneOf(Class<E>)` is declared `<E extends Enum<E>>`. Real code adds `& SomeInterface` when the API needs the enum to also do something. ## How the earlier rules interact - **Class-first ordering:** `Enum` is a **class**, so it must be the **leftmost** bound — `<T extends HasCode & Enum<T>>` would be a compile error. - **Erasure:** T erases to the leftmost bound, `Enum`. So inside the method, `value` is, after erasure, an `Enum`, and calls to `HasCode` members get a synthetic cast to `HasCode` (see the erasure question). - **At most one class bound:** still holds — `Enum` is the single class; everything else must be an interface. ## Why not just take `Enum<?>` or the interface alone? - Taking only `HasCode` would accept non-enum implementers, losing the enum-only guarantee and the `Enum` methods. - Taking only `Enum<T>` would lose the `HasCode` capability. - The intersection `Enum<T> & HasCode` is the precise contract, and the recursive `Enum<T>` keeps the enum methods self-typed (e.g. `compareTo(T)` rather than `compareTo(Enum)`). ## Caveats - These signatures get **verbose and intimidating**; document them well. - Self-types don't fully prevent abuse (a misbehaving subtype could declare `class A implements Comparable<B>`), but for `enum` the language guarantees the self-type, which is why the enum pattern is robust. ## First-principles summary Recursive bounds let a parameterized constraint refer to T itself (`Comparable<T>`, `Enum<T>`), capturing 'self-typed' behavior and exact return types. Combining them with `&` (e.g. `<T extends Enum<T> & SomeInterface>`) demands both 'is this exact enum kind' and 'has this capability' — the standard way to write enum-restricted, capability-restricted APIs. The class-first, single-class, and erasure rules all still apply, with `Enum` as the mandatory leftmost class bound.
- Why is Enum<T> written recursively instead of just Enum?So enum methods are self-typed to the exact enum: compareTo takes T, getDeclaringClass()/values relate to T, and APIs can return the precise enum type rather than the raw Enum supertype.
- In <T extends Enum<T> & HasCode>, why must Enum come before HasCode?Enum is a class and HasCode is an interface; the class bound must be leftmost. Reversing them is a compile error, and T erases to Enum (the leftmost bound).
saying these in an interview costs you the question
- Writing <T extends SomeInterface & Enum<T>> — Enum is a class and must come first; this won't compile.
- Thinking the recursive bound is just decoration — it makes methods self-typed (compareTo(T), return T) instead of using a supertype.
- Believing self-typing fully prevents misuse for arbitrary classes — only enums get the language-guaranteed self-type; ordinary classes can lie (implements Comparable<Other>).