🪆 Enums, Records & Nested Types · Intermediate

Enums with fields & methods in Java

Constructors (implicitly private), fields, methods, constant-specific bodies.

🧩 The mysteryUse just ONE constant of an enum, and Java secretly builds ALL of them. Why would it do that?

Enums are full classes

An enum can have fields, a constructor and methods. Arguments after a constant, like PENNY(1), are passed to the constructor, which runs once per constant. So each constant carries its own data.

enum Coin {
    PENNY(1), NICKEL(5), DIME(10);
    final int cents;
    Coin(int cents) { this.cents = cents; }
}
Coin.DIME.cents;   // 10

Constructor rules

The enum constructor is implicitly private — writing public is a compile error, because nobody outside may create new constants. And when the enum has other members, the constant list comes first and must end with a semicolon.

enum Coin {
    PENNY(1), DIME(10);   // <- semicolon!
    final int cents;
    private Coin(int c) { cents = c; } // ok
    // public Coin(...)  -> compile error
}
🔮 Predict it

Who gets built?

Only GO is used. What prints?

enum Signal {
    STOP, GO;
    Signal() { System.out.print(name() + " "); }
}
void main() {
    Signal a = Signal.GO;
    Signal b = Signal.GO;
    System.out.println(a == b);
}
  1. STOP GO true
  2. GO true
  3. GO GO true
  4. STOP GO false
Show the answer

The first use initializes the whole enum, which constructs all constants, once, in order. Later uses reuse the same objects, so a == b is true.

⚠️ The trap

The missing semicolon

With fields or methods after the constants, forgetting the ; that ends the constant list is a compile error. The compiler reads final double gravity as if it were another constant.

enum Planet {
    MERCURY(3.7), EARTH(9.8)     // error
    final double gravity;
    Planet(double g) { gravity = g; }
}

Constant-specific bodies

A constant can have its own class body overriding a method. Declare an abstract method in the enum, and every constant must implement it. MUL.apply(3, ADD.apply(1, 1)) is 3 * 2 = 6.

enum Op {
    ADD {
        int apply(int a, int b) { return a + b; }
    },
    MUL {
        int apply(int a, int b) { return a * b; }
    };
    abstract int apply(int a, int b);
}
🤔 Think first

Why not a switch?

You could write one apply method with a switch over this. Why might constant-specific bodies be safer?

Think about it, then reveal the answer

Add a new constant and the compiler forces you to give it a body (the method is abstract). With a switch, a forgotten case can slip by. The behaviour also lives right next to the constant it belongs to.

💼 In the real world

Enums with brains

java.util.concurrent.TimeUnit is an enum whose constants carry conversion logic: TimeUnit.MINUTES.toSeconds(2) returns 120. Real apps use the same idea for currencies with symbols, HTTP statuses with codes, or pricing tiers with limits.

Key takeaways

  1. PENNY(1) passes 1 to the constructor
  2. Enum constructors are implicitly private; public is a compile error
  3. List the constants first and end the list with ; before other members
  4. Constant bodies: ADD { int apply(...) { ... } }
🤯 Did you know?

A constant with its own body is compiled as an anonymous subclass of the enum, so Op.ADD.getClass() is not Op.class — use getDeclaringClass() to get the enum type back.

Practice questions

What does this print?

enum Coin {
    PENNY(1), NICKEL(5), DIME(10);
    final int cents;
    Coin(int c) { cents = c; }
}
void main() {
    int sum = 0;
    for (Coin c : Coin.values()) sum += c.cents;
    System.out.println(sum);
}
  1. 16
  2. 3
  3. 0
  4. Compile error
Check your answer

16. Each constant stored its own cents value via the constructor: 1 + 5 + 10 = 16.

What does this print?

enum Light {
    RED, GREEN;
    Light() { System.out.print(name() + " "); }
}
void main() {
    Light a = Light.GREEN;
    Light b = Light.GREEN;
    System.out.println(a == b);
}
  1. RED GREEN true
  2. GREEN GREEN true
  3. GREEN true
  4. RED GREEN false
Check your answer

RED GREEN true. The first use of Light initializes the enum, which constructs ALL constants once. Later uses reuse the same objects, so a == b.

Next: switch over an enum and the compiler starts checking your homework — miss one constant and it won't compile.