Why is java.lang.Enum declared as Enum<E extends Enum<E>>?
answer
- enum X compiles to class X extends Enum<X>
- Enum implements Comparable<E> → same-enum compareTo only
- getDeclaringClass returns Class<E> (precise)
- Backs type-safe EnumSet/EnumMap
- Canonical library use of a recursive bound
basics
~20 sSo 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.
solid answer
~40 sEnum uses a recursive bound, Enum<E extends Enum<E>>, so that the abstract supertype can express type-safe, self-referential operations specialized to each concrete enum. Concretely, Enum implements Comparable<E>, so compareTo only accepts a value of the *same* enum — you can compare two Days but the compiler stops you comparing a Day to a Month. The bound also lets methods like getDeclaringClass() return Class<E> (the precise enum type) and underpins type-safe EnumSet/EnumMap which are keyed by E. Each enum the compiler generates, e.g. enum Day, becomes class Day extends Enum<Day>, satisfying the bound by passing itself. This is the language library's canonical real-world use of a recursive generic bound — it gives you ordinal-based ordering that's safe per enum type without any per-enum boilerplate.
code
java · 8 lines// Conceptual: what the compiler generates
enum Day { MON, TUE }
// becomes ~ final class Day extends Enum<Day> { ... }
Day.MON.compareTo(Day.TUE); // OK, compares ordinals
// Day.MON.compareTo(Month.JAN); // compile error: Month is not a Day
Class<Day> c = Day.MON.getDeclaringClass(); // precise type, thanks to Ego deeper
Knows enums are comparable and you can't compare two different enum types, without needing the generic detail.
Connects the no-cross-enum-comparison behavior to Enum implementing Comparable<E>.
States the full Enum<E extends Enum<E>> declaration and lists the benefits: same-type compareTo, precise Class<E>, EnumSet/EnumMap safety.
Uses Enum as the exemplar when justifying a recursive bound in API design, and can contrast it with hand-rolled self-typed hierarchies and their weaker compiler guarantees.
## What an enum compiles to When you write `enum Day { MON, TUE }`, the compiler turns it into a class roughly like `final class Day extends java.lang.Enum<Day>` with `MON` and `TUE` as static constants. So every enum is a subclass of the library class `Enum`, and it passes *itself* as the type argument — exactly the CRGP shape. ## The declaration `java.lang.Enum` is declared: ```java public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable ``` The recursive bound `<E extends Enum<E>>` means "E is an enum type parameterized by itself." Why does the library need this? ## Reason 1: type-safe ordering via Comparable<E> `Enum implements Comparable<E>`. Because `E` is the self type, `compareTo` has signature `int compareTo(E o)` — it accepts only the *same* enum type. The implementation just compares `ordinal()` (declaration position). The payoff: ```java Day.MON.compareTo(Day.TUE); // OK // Day.MON.compareTo(Month.JAN); // compile error: different enum types ``` Without the recursive bound, `Enum` could only be `Comparable<Enum>` or raw, and the compiler would let you compare values from two unrelated enums — a meaningless, bug-prone operation. ## Reason 2: precise return types `getDeclaringClass()` returns `Class<E>`, the *exact* enum class, not `Class<? extends Enum>`. Generic code that takes an enum can therefore recover the specific type. `Enum.valueOf(Class<T> enumType, String name)` likewise uses the bound to tie the class token to the returned constant type. ## Reason 3: type-safe enum collections `EnumSet<E extends Enum<E>>` and `EnumMap<K extends Enum<K>, V>` reuse the same bound. An `EnumSet<Day>` can only hold `Day` constants; the bound is what lets these collections be both extremely efficient (bit-vector / array backed by `ordinal()`) and statically type-safe. ## Why not just `Enum<E>` without the bound? A plain `Enum<E>` would let you write `class Weird extends Enum<String>` (well, ignoring that enums are compiler-generated) and would not constrain `E` to actually be an enum or to be the self type, breaking the `Comparable<E>` and ordinal contracts. The self-bound expresses the real invariant: "the type parameter is this very enum." ## Key takeaways - Enum is the textbook *library* example of a recursive generic bound / CRGP. - The bound delivers: same-type-only `compareTo`, precise `Class<E>`/`valueOf` typing, and type-safe `EnumSet`/`EnumMap`. - You never write the bound yourself for enums — the compiler does `enum X` → `class X extends Enum<X>` automatically — but understanding it explains why cross-enum comparison won't compile.
- What stops you from comparing Day.MON.compareTo(Month.JAN)?Enum implements Comparable<E> where E is the self enum type, so Day's compareTo accepts only a Day. Passing a Month is a compile error — the recursive bound enforces same-type comparison.
- Can you extend java.lang.Enum directly in your own class?No. The compiler forbids extending Enum explicitly; you must use the enum keyword, which generates the extends Enum<Self> for you. This keeps the self-bound invariant intact.
saying these in an interview costs you the question
- Saying the bound is just decorative — it actively blocks cross-enum compareTo
- Thinking you write Enum<X> by hand — the compiler generates it
- Believing enums can be compared across types because they all extend Enum