iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Enums

Java enums are full classes with fields, methods, and constructors — not just labels. Use them for closed sets of values with associated behaviour: status machines, parsing keys, strategy selection, configuration. Combined with switch expressions (Java 14+) they enable exhaustive pattern matching.

Constants, methods, switch, EnumMap

EXAMPLE
// 1) Simplest enum
public enum Direction { NORTH, EAST, SOUTH, WEST }

Direction d = Direction.NORTH;
d.name();                                            // 'NORTH'
d.ordinal();                                         // 0  (avoid using; depends on order)
Direction.values();                                  // [NORTH, EAST, SOUTH, WEST]
Direction.valueOf("NORTH");                         // Direction.NORTH

// 2) Enum with fields + methods
public enum Planet {
    MERCURY(3.303e23, 2.4397e6),
    VENUS  (4.869e24, 6.0518e6),
    EARTH  (5.976e24, 6.37814e6),
    MARS   (6.421e23, 3.3972e6);

    private final double mass;
    private final double radius;

    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }

    public double mass()   { return mass; }
    public double radius() { return radius; }

    public double surfaceGravity() {
        return 6.67300E-11 * mass / (radius * radius);
    }
}

System.out.println(Planet.EARTH.surfaceGravity());   // ~9.81

// 3) Switch expressions (Java 14+) — exhaustive on enums
static String description(Direction d) {
    return switch (d) {
        case NORTH -> "up";
        case EAST  -> "right";
        case SOUTH -> "down";
        case WEST  -> "left";
    };
}

// Compiler enforces every case is handled. Add a new enum value → compile errors fast.

// 4) Per-constant behaviour with abstract methods
public enum Operation {
    PLUS  { public int apply(int a, int b) { return a + b; } },
    MINUS { public int apply(int a, int b) { return a - b; } },
    TIMES { public int apply(int a, int b) { return a * b; } },
    DIVIDE{ public int apply(int a, int b) { return a / b; } };

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

int result = Operation.PLUS.apply(3, 4);             // 7

// Each constant supplies its own implementation. Cleaner than a switch.

// 5) Implementing interfaces
public interface Describable { String describe(); }

public enum HttpMethod implements Describable {
    GET   { public String describe() { return "Read"; } },
    POST  { public String describe() { return "Create"; } },
    PUT   { public String describe() { return "Replace"; } },
    PATCH { public String describe() { return "Update"; } },
    DELETE{ public String describe() { return "Delete"; } };
}

// 6) EnumSet — fast set of enum constants
import java.util.EnumSet;
EnumSet<HttpMethod> safe = EnumSet.of(HttpMethod.GET, HttpMethod.HEAD);
safe.contains(HttpMethod.GET);                       // true

EnumSet<Direction> horizontal = EnumSet.of(Direction.EAST, Direction.WEST);

// EnumSet is a BITFIELD under the hood; very fast.

// 7) EnumMap — fast map keyed by enum
import java.util.EnumMap;
Map<Direction, Integer> dx = new EnumMap<>(Direction.class);
dx.put(Direction.NORTH, 0);
dx.put(Direction.EAST,  1);
dx.put(Direction.SOUTH, 0);
dx.put(Direction.WEST, -1);

// 8) Singleton pattern — enum is the canonical implementation
public enum DateUtil {
    INSTANCE;

    public LocalDate today() { return LocalDate.now(); }
}

DateUtil.INSTANCE.today();

// Thread-safe, serialisation-safe, reflection-resistant.

// 9) Generic enum-keyed maps
Map<HttpMethod, List<String>> headers = new EnumMap<>(HttpMethod.class);
headers.put(HttpMethod.GET, List.of("Accept"));
headers.put(HttpMethod.POST, List.of("Content-Type", "Authorization"));

// 10) Pattern matching switch (Java 21+) — combine with sealed for richer hierarchies
sealed interface Shape permits Circle, Square {}
record Circle(double r) implements Shape {}
record Square(double s) implements Shape {}

static double area(Shape s) {
    return switch (s) {
        case Circle c -> Math.PI * c.r() * c.r();
        case Square q -> q.s() * q.s();
    };
}

// 11) Enums in Spring / Jackson / JPA
// Jackson serialises enum to NAME by default; configure via @JsonValue:
//   public enum Status { @JsonValue ACTIVE, ARCHIVED }

// JPA
@Enumerated(EnumType.STRING)  // store enum name in DB
private Status status;
// Avoid EnumType.ORDINAL — adding values reorders ordinals + breaks data

// 12) Parsing user input safely
public static Optional<HttpMethod> fromString(String input) {
    try {
        return Optional.of(HttpMethod.valueOf(input.toUpperCase()));
    } catch (IllegalArgumentException e) {
        return Optional.empty();
    }
}

// 13) Enum vs sealed interface + records
// • Enum — fixed constants with possible behaviour
// • Sealed interface + records — variants with DIFFERENT fields per variant
// E.g. Event types: OrderPlaced(id, total) vs OrderShipped(id, carrier) — sealed wins
//      Status: ACTIVE / ARCHIVED / DELETED — enum wins

// 14) Enum constants with overrides
public enum LogLevel {
    DEBUG { public boolean enabled() { return Config.debug; } },
    INFO  { public boolean enabled() { return true; } },
    ERROR { public boolean enabled() { return true; } };

    public abstract boolean enabled();
}

// 15) Common bugs
// • Using ordinal() in persistence → adding enum values reorders them; use name() instead
// • valueOf with unknown name → IllegalArgumentException; wrap in Optional / try-catch
// • Comparing enums with .equals() — works but == is canonical (single instance)
// • Forgetting case in a non-exhaustive switch — Java warns / errors on enum switch missing cases when target is sealed
// • Mutable fields in enums — they're singletons; mutating affects everyone
// • Storing huge data per enum constant → loaded at class init; consider lazy initialisation
// • Using EnumSet across multiple enum types → can't; one type per set
// • Returning .values() repeatedly in a loop — array allocation; cache it
// • Auto-generated default case in switch — drop it if switch is exhaustive (compiler enforces)

Why it matters

Java enums are full classes — lean on fields, methods, abstract per-constant behaviour, and EnumSet/EnumMap for fast collections keyed by the enum. Use switch expressions for exhaustive matching, store enums in databases as STRING (never ORDINAL), and reach for sealed interfaces when variants need different fields.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }
Day d = Day.FRI;
if (d == Day.FRI) System.out.println("🎉");
Try it Yourself »

Discussion

Loading…