What do the built-in enum methods values(), valueOf(), name(), and ordinal() do, and what are their costs and caveats?
answer
- values(): new array each call, declaration order, cache in loops
- valueOf(name): exact, case-sensitive, matches name() not toString(); IAE/NPE
- name(): final, exact declared identifier; inverse of valueOf
- ordinal(): zero-based position, unstable, never persist
- Need a stable number? add a final field, not ordinal()
basics
~20 svalues() returns an array of all constants in declaration order. valueOf("NAME") returns the constant with that exact name (throws if none). name() returns the constant's declared name as a String. ordinal() returns its zero-based position in the declaration list.
solid answer
~50 sEvery enum gets four built-ins. The compiler synthesizes a static `values()` that returns a fresh array of all constants in declaration order, and a static `valueOf(String)` that looks up a constant by its exact declared name, throwing IllegalArgumentException if the name does not match (and NullPointerException on null). From java.lang.Enum each constant inherits `name()`, returning the exact declared identifier as a String, and `ordinal()`, returning its zero-based index in the declaration order. Two caveats matter: `values()` allocates a **new array on every call** (it must, to keep the internal array unmodifiable), so cache it in hot loops; and `ordinal()` is **brittle** — its value shifts if you reorder or insert constants, so you must never persist or serialize ordinal as a stable identifier. Prefer an explicit field for any meaningful number. `valueOf` is also case-sensitive and matches `name()`, not `toString()`, so overriding `toString` does not change `valueOf`.
code
java · 12 linesenum Level { LOW, MEDIUM, HIGH }
Level[] all = Level.values(); // [LOW, MEDIUM, HIGH], new array each call
Level hi = Level.valueOf("HIGH"); // HIGH; throws IllegalArgumentException for "high"
String nm = Level.MEDIUM.name(); // "MEDIUM"
int idx = Level.MEDIUM.ordinal(); // 1 (zero-based, position-dependent)
// Safe parse of untrusted input:
Level parse(String s) {
try { return Level.valueOf(s); }
catch (IllegalArgumentException | NullPointerException e) { return Level.LOW; }
}go deeper
Knows values() lists all constants, valueOf(name) looks one up, name() gives the string, ordinal() gives the position.
Explains the allocation cost of values(), the IAE/NPE from valueOf, that valueOf is case-sensitive and uses name(), and the ordinal-instability caveat.
Recommends caching values(), guarding valueOf on untrusted input, never persisting ordinal, and backing stable codes with explicit fields; knows name() vs toString().
Establishes team conventions for enum (de)serialization (by name or explicit code, never ordinal), versioning/compatibility when adding constants, and parsing strategies for external inputs at API boundaries.
## The four built-ins Every enum automatically exposes four methods. Two are **static** and synthesized by the compiler on the enum type; two are **instance** methods inherited from `java.lang.Enum`. ### values() — static ```java for (Day d : Day.values()) { ... } ``` `values()` returns an **array containing every constant, in declaration order**. It is generated by the compiler (it is not in `Enum` itself). Important detail: it returns a **new array each call**. The enum holds one canonical internal array; handing out a copy prevents callers from mutating the shared set (arrays in Java are mutable). In a tight loop, call it once and cache the result, or use `EnumSet`/`EnumMap` instead of repeatedly scanning the array. ### valueOf(String) — static ```java Day d = Day.valueOf("MONDAY"); ``` `valueOf` returns the constant whose **declared name exactly matches** the argument. It is **case-sensitive** and matches the real name, i.e. what `name()` returns — **not** `toString()`. If no constant matches it throws **`IllegalArgumentException`**; if the argument is `null` it throws **`NullPointerException`**. So parsing untrusted input with `valueOf` requires a try/catch or a pre-check. (There is also a more general `Enum.valueOf(Class, String)`; the per-enum `valueOf` is the convenient form.) ### name() — instance ```java String s = Day.MONDAY.name(); // "MONDAY" ``` `name()` returns the **exact declared identifier** as a `String`. It is `final` — you cannot override it. Use `name()` (not `toString()`) when you need a stable, programmatic name, because someone may override `toString()` to a display form. `name()` is the inverse of `valueOf()`: `Day.valueOf(d.name()) == d`. ### ordinal() — instance ```java int i = Day.WEDNESDAY.ordinal(); // 2 (zero-based) ``` `ordinal()` returns the **zero-based position** of the constant in the declaration list. It exists mainly to make `EnumSet`/`EnumMap` extremely fast (they index a bitset/array by ordinal). **The ordinal trap:** ordinals are **positional and unstable**. If you reorder the constants or insert a new one in the middle, every later ordinal shifts. Therefore you must **never** persist an ordinal to a database, file, or wire protocol, nor derive business meaning from it. If you need a stable numeric code, **add an explicit final field** and store that. Effective Java's rule: "Never derive a value associated with an enum from its ordinal; store it in an instance field instead." ## Quick reference | Method | Static? | Returns | Throws | Caveat | |---|---|---|---|---| | `values()` | yes (synthesized) | new array of all constants | — | allocates each call; cache in loops | | `valueOf(String)` | yes (synthesized) | matching constant | IAE if no match, NPE if null | case-sensitive, matches name() not toString() | | `name()` | no (from Enum, final) | declared name String | — | stable identifier; prefer over toString for logic | | `ordinal()` | no (from Enum, final) | zero-based index | — | unstable across reordering; never persist | ## Summary Use `values()` to iterate (but cache it), `valueOf`/`name()` as an inverse pair for stable name lookup (guarding the IAE/NPE), and avoid `ordinal()` for anything persisted — back meaningful numbers with your own field.
- Why is using ordinal() to assign business meaning dangerous?Ordinal is purely positional: it equals the constant's index in the declaration list. Reordering constants or inserting one in the middle silently changes every later ordinal, so any persisted or transmitted ordinal then maps to the wrong constant. Store meaningful values in an explicit final field instead, which stays correct regardless of order.
- If you override toString() on an enum, does valueOf still work with the new string?No. valueOf matches the constant's declared name() (the source identifier), not toString(). Overriding toString changes only the display form; you would still call valueOf with the original NAME. To parse a custom display string you need your own lookup, e.g. a static Map from display string to constant.
saying these in an interview costs you the question
- Persisting ordinal() to a DB/wire format as a stable id
- Assuming valueOf matches toString() or is case-insensitive
- Not handling IllegalArgumentException/NPE from valueOf on untrusted input
- Calling values() inside a hot loop without caching the array
- Thinking name() can be overridden (it is final)