Enums and Nested Types

Learning goals

Model fixed sets of constants with enums, attach behavior and fields to enum constants, and use nested types (static vs inner) without memory leaks or confusing syntax.


Basic enums

public enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

Day today = Day.MONDAY;
if (today == Day.SATURDAY) { ... }

Enums are classes extending java.lang.Enum—singleton instances, type-safe constants. Prefer over public static final int magic numbers.

switch (today) {
    case MONDAY -> System.out.println("Start");
    case FRIDAY -> System.out.println("Almost weekend");
    default -> { }
}

Enums with fields and methods

public enum Planet {
    EARTH(5.972e24, 6.371e6),
    MARS(6.39e23, 3.389e6);

    private final double massKg;
    private final double radiusM;

    Planet(double massKg, double radiusM) {
        this.massKg = massKg;
        this.radiusM = radiusM;
    }

    public double surfaceGravity() {
        double G = 6.674e-11;
        return G * massKg / (radiusM * radiusM);
    }
}

Each constant calls its constructor once at class load.


Enum methods

public enum Status {
    PENDING, ACTIVE, CLOSED;

    public boolean isOpen() {
        return this == ACTIVE || this == PENDING;
    }

    public static Status fromCode(String code) {
        return switch (code) {
            case "P" -> PENDING;
            case "A" -> ACTIVE;
            case "C" -> CLOSED;
            default -> throw new IllegalArgumentException(code);
        };
    }
}

values() and valueOf(String) are generated—parse carefully with validation.


Enum implementing interfaces

public enum Op implements Calculator {
    PLUS {
        public int apply(int a, int b) { return a + b; }
    },
    MINUS {
        public int apply(int a, int b) { return a - b; }
    };

    public abstract int apply(int a, int b);
}

Strategy pattern with fixed set of implementations.


Nested classes

Static nested — does not capture outer instance:

public class Outer {
    static class Nested {
        void hello() { System.out.println("nested"); }
    }
}

Outer.Nested n = new Outer.Nested();

Inner class — holds implicit reference to outer:

public class Outer {
    private int value = 42;

    class Inner {
        void print() {
            System.out.println(value);  // Outer.this.value
        }
    }
}

Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();

Local and anonymous classes

Runnable r = new Runnable() {
    @Override
    public void run() {
        System.out.println("once");
    }
};

Lambdas replace many anonymous classes for SAM interfaces:

Runnable r2 = () -> System.out.println("once");

When to use nested types

Type Use
Static nested Helper grouped with outer; no outer state
Inner Needs outer instance state; iterator pattern
Local Tiny one-off inside method (rare with lambdas)
Enum Fixed constant set with behavior

Common mistakes

  1. enum with public mutable fields — treat constants as immutable.
  2. Inner class in static context without outer instance — need outer.new Inner().
  3. Memory leak: non-static inner held long-lived — inner retains outer; prefer static nested + weak ref if needed.
  4. Ordinal for business logicordinal() breaks when reordering; use explicit fields.
  5. Switch on enum without default — exhaustiveness OK for enums, but handle new enum values when evolving API.

Practice checkpoint

  1. Define Priority { LOW, MEDIUM, HIGH } with method isHigh().

    • Answer: return this == HIGH;
  2. Difference static nested vs inner?

    • Answer: Static has no outer reference; inner requires outer instance.
  3. Safe parse: Day.valueOf("MON")?

    • Answer: Throws IllegalArgumentException; validate input.
  4. Replace anonymous Comparator with lambda.

    • Answer: (a, b) -> Integer.compare(a.size(), b.size())

Interview angles

  • “Enum singleton?” — Effective singleton pattern (Joshua Bloch); serialization-safe.
  • “Can enum extend class?” — No (extends Enum implicitly); can implement interfaces.
  • “Why static nested for Builder?” — Builder doesn’t need enclosing instance; avoids extra reference.

Next: /java/learn/core/exceptions/