skip to content

An enum can carry fields and a constructor. How does that interact with ordinal(), name(), and constant-specific behavior?

level: juniorimportance: should knowfreq 45%

answer

  1. Each constant passes args to an implicitly-private constructor
  2. final fields -> immutable per-constant data (Planet mass/radius)
  3. name() = source identifier (final); ordinal() = declaration index
  4. Prefer name()/valueOf over ordinal() for logic & storage
  5. values() returns all constants in order

basics

~20 s

Each constant can pass arguments to a private enum constructor to set its own fields, like Planet(mass, radius). name() returns the constant's identifier text and ordinal() its position. You read fields through getters; ordinal/name come for free.

solid answer

~40 s

An enum can declare instance fields and a constructor; each constant supplies the constructor arguments in parentheses, e.g. `MERCURY(3.3e23, 2.4e6)`. The constructor is implicitly private (you can't call it elsewhere), and it runs once per constant during class initialization, so the per-constant state is effectively immutable if you make the fields final. Separately, every constant gets `name()` (the exact identifier you wrote) and `ordinal()` (its zero-based declaration position) for free from java.lang.Enum. These are distinct from your own fields: prefer name() over a hand-rolled string field, and avoid relying on ordinal() for logic or storage since it shifts if constants are reordered. Constant-specific behavior (bodied constants overriding methods) can combine with fields, so a constant can both hold data and compute differently.

code

java · 13 lines
java
enum Coin {
    PENNY(1), NICKEL(5), DIME(10), QUARTER(25);

    private final int cents;
    Coin(int cents) { this.cents = cents; }   // implicitly private

    int cents() { return cents; }
}

int v = Coin.QUARTER.cents();        // 25
String n = Coin.QUARTER.name();      // "QUARTER"
int o = Coin.QUARTER.ordinal();      // 3
Coin c = Coin.valueOf("DIME");       // Coin.DIME

go deeper

for a junior

Knows constants can pass constructor args to set fields, and that name()/ordinal()/values()/valueOf exist.

for a middle

Uses final fields for immutable per-constant data and prefers name()/valueOf over ordinal() for persistence.

for a senior

Explains the implicit-private constructor, per-constant initialization timing, and why ordinal is reserved for EnumSet/EnumMap, not logic.

for a principal

Sets team conventions around enum persistence (name not ordinal), considers schema evolution, and combines field data with constant-specific behavior cleanly.

## Enums are classes with fixed instances An `enum` is really a class whose instances are the listed constants. Like any class it can have **instance fields**, a **constructor**, and **methods** — the twist is that you can't `new` it; the constants are created for you. ## Per-constant fields via the constructor Give the enum fields and a constructor, then each constant **passes arguments** in parentheses: ```java enum Planet { MERCURY(3.303e23, 2.4397e6), EARTH (5.976e24, 6.37814e6); // each constant calls the constructor private final double mass; // in kilograms private final double radius; // in meters Planet(double mass, double radius) { // implicitly private this.mass = mass; this.radius = radius; } double surfaceGravity() { return 6.67300E-11 * mass / (radius * radius); } } ``` Key points: - The **constructor is implicitly `private`** — you cannot declare it `public`/`protected`, and you can't call it anywhere except via the constant declarations. This is what keeps the instance set closed. - The constructor runs **once per constant**, in declaration order, during the enum's class initialization. Make fields `final` for an effectively immutable constant. - Constants with constructor arguments and constants with method bodies can be combined: `EARTH(5.97e24, 6.37e6) { double greeting() {...} }`. ## name() vs ordinal() vs your fields `java.lang.Enum` gives every constant two free accessors: - **`name()`** returns the **exact identifier** as written in source, e.g. `Planet.EARTH.name()` -> `"EARTH"`. `toString()` defaults to the same but can be overridden; `name()` is `final` and cannot. - **`ordinal()`** returns the **zero-based position** in declaration order: `MERCURY.ordinal()` -> 0, `EARTH.ordinal()` -> 1. These are **separate** from any fields you declare. Guidance: - Don't create your own `String code` field that just duplicates the constant name — use `name()`. - **Avoid `ordinal()` for logic or persistence.** It's documented as existing mainly for `EnumSet`/`EnumMap`; using it in business logic or storing it makes your code brittle, because inserting or reordering constants silently shifts every later ordinal. Store/match on `name()` and convert back with `valueOf("EARTH")`. ## valueOf and values() Two more generated helpers complete the picture: `Planet.valueOf("EARTH")` returns the constant for that name (throws `IllegalArgumentException` if none), and `Planet.values()` returns a fresh array of all constants in declaration order — handy for iteration. ## Putting it together Use the constructor + final fields to attach immutable data to each constant; use `name()`/`valueOf` for stable string identity; reach for constant-specific bodies when each constant must *behave* differently as well. Keep `ordinal()` out of your logic.

  • Why can't you make an enum constructor public?
    Enum constructors are implicitly private so the set of instances stays closed — only the declared constants can invoke it. Declaring it public/protected is a compile error.
  • Why prefer name() over ordinal() when storing an enum value?
    name() is a stable string tied to the identifier, while ordinal() is just a position that changes if you reorder or insert constants — persisting it silently corrupts data.

The enum is a class roster where every student (constant) is pre-enrolled with a fixed ID badge: name() is the name printed on the badge, ordinal() is just their seat number — fine for seating charts, dangerous to use as a permanent identity.

saying these in an interview costs you the question

  • Making the enum constructor public or calling it directly.
  • Storing or branching on ordinal() in business logic / databases.
  • Adding a redundant string field that just mirrors name().
  • Assuming values() returns a cached array — it returns a fresh copy each call.

context