🪆 Enums, Records & Nested Types · Intermediate

Enum basics in Java

Fixed set of constants; values(), valueOf(), ordinal(), name().

🧩 The mysteryA teammate adds one word to a list of order statuses — and thousands of shipped orders suddenly read back as "packed". One innocent-looking method caused it.

A closed list of choices

An enum defines a fixed set of named constants. Each constant is a single object of the enum type, created once. Because there's exactly one Size.MEDIUM, you can safely compare constants with **==** — it's even null-safe, unlike calling equals on a null.

enum Size { SMALL, MEDIUM, LARGE }
 
Size s = Size.MEDIUM;
if (s == Size.MEDIUM) { }

Free methods on every enum

**values() returns all constants in declaration order (not alphabetical). valueOf("SMALL") looks one up by its exact, case-sensitive name. Each constant has name() — its identifier as written — and ordinal(), its position starting at 0**.

enum Day { WED, MON, TUE }
Day.values()[0];     // WED
Day.valueOf("MON");  // MON
Day.TUE.ordinal();   // 2
🔮 Predict it

Name and number

What does this print?

enum Planet { VENUS, EARTH, MARS }
void main() {
    Planet p = Planet.MARS;
    String s = p.name() + " " + p.ordinal();
    System.out.println(s);
}
  1. MARS 2
  2. MARS 3
  3. mars 2
Show the answer

name() returns the identifier exactly as declared, and ordinals start at 0: VENUS 0, EARTH 1, MARS 2.

🔮 Predict it

Close enough?

What happens when the case doesn't match?

enum Planet { VENUS, EARTH, MARS }
void main() {
    System.out.println(Planet.valueOf("Earth"));
}
  1. EARTH
  2. null
  3. Throws IllegalArgumentException
Show the answer

valueOf needs the exact constant name. "Earth" isn't "EARTH", so it throws IllegalArgumentException — it never returns null.

⚠️ The trap

Saving ordinals

Storing status.ordinal() in a database is a time bomb. Statuses were NEW(0), PAID(1), SHIPPED(2). Insert PACKED after PAID and every old "2" now reads back as PACKED. Ordinals depend on declaration order — store **name()** instead.

enum Status { NEW, PAID, PACKED, SHIPPED }
// old rows saved 2 for SHIPPED...
// ...2 now means PACKED!
💼 In the real world

A famous default

JPA (the standard Java persistence API) saves enums by ordinal unless you write @Enumerated(EnumType.STRING). Many teams discovered this only after someone reordered constants in production. Experienced developers add that annotation by reflex.

Key takeaways

  1. enum Size { SMALL, MEDIUM, LARGE }
  2. values() returns constants in declaration order
  3. valueOf("SMALL") is case-sensitive; unknown names throw IllegalArgumentException
  4. ordinal() starts at 0 and changes if constants are reordered

💡 The sizes on a coffee menu: a short, fixed list you can't add to at the counter.

🤯 Did you know?

Enums arrived in Java 5 (2004). That made enum a keyword, so older code that used enum as a variable name — common for an Enumeration — stopped compiling.

Practice questions

What does this print?

enum Size { SMALL, MEDIUM, LARGE }
void main() {
    Size s = Size.MEDIUM;
    System.out.println(s.name() + " " + s.ordinal());
}
  1. MEDIUM 1
  2. MEDIUM 2
  3. medium 1
  4. 1 MEDIUM
Check your answer

MEDIUM 1. name() returns the exact identifier, and ordinals start at 0, so MEDIUM is position 1.

What does this print?

enum Size { SMALL, MEDIUM, LARGE }
void main() {
    System.out.println(Size.valueOf("large"));
}
  1. LARGE
  2. large
  3. null
  4. Throws IllegalArgumentException
Check your answer

Throws IllegalArgumentException. valueOf needs the exact constant name. "large" doesn't match LARGE, so it throws instead of returning null.

Next: enums aren't just names. A Coin constant can carry its value in cents — and even its own methods.