Enums

This section documents the current Java release line, with Java 25 LTS as the reference point (no specific patch version is pinned), as published at the Java developer portal, the Java Tutorials, and the Java SE API specification — which are the references these pages are written and verified against.

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

An enum declares a fixed, compile-time set of named constant instances of a type. This page covers the members every enum gets for free, using an enum in a switch, attaching data and behaviour to constants, and the EnumSet / EnumMap collections that are tuned for enum keys.

Enum constants and the members every enum gets

Each constant listed in an enum body is a public static final instance of that enum type, created once by the JVM. Every enum implicitly extends java.lang.Enum, which supplies name(), ordinal(), a natural-order compareTo, and final equals/hashCode (so == is always safe for comparison). The compiler additionally synthesises a static values() returning a fresh array of the constants and a static valueOf(String) that maps a name back to its constant. See the Java Tutorials Enum Types and JLS 8.9, Enum Classes.

public enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }
Day d = Day.WEDNESDAY;

System.out.println(d.name());              // WEDNESDAY
System.out.println(d.ordinal());           // 2  (zero-based position in declaration order)
System.out.println(Day.valueOf("FRIDAY")); // FRIDAY

for (Day day : Day.values()) {
    System.out.println(day);               // toString() defaults to name()
}

// valueOf with a name that is not a constant throws IllegalArgumentException
// Day.valueOf("Funday");

Treat ordinal() as an implementation detail: it changes silently if constants are reordered, so never persist or serialise it — store name() instead.

Enums in switch

In a switch on an enum, case labels use the bare constant name, never Day.SATURDAY. A switch expression whose arms cover every constant needs no default, and the compiler flags a constant that is missed — so adding a new constant turns silent fall-through into a compile error. See Switch Expressions on dev.java.

static boolean isWeekend(Day day) {
    return switch (day) {
        case SATURDAY, SUNDAY -> true;
        case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> false;
    };
}

System.out.println(isWeekend(Day.SUNDAY));   // true

Enums with fields, a constructor, and methods

Constants can carry data. Declare private final fields, a constructor (implicitly private — you can never call it yourself), and pass the arguments for each constant in parentheses after its name.

public enum Planet {
    MERCURY(3.303e23, 2.4397e6),
    EARTH  (5.976e24, 6.37814e6),
    JUPITER(1.900e27, 7.14920e7);

    private static final double G = 6.67300E-11;

    private final double massKg;
    private final double radiusM;

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

    public double surfaceGravity() {
        return G * massKg / (radiusM * radiusM);
    }
}
for (Planet p : Planet.values()) {
    System.out.printf("%-8s g = %.2f m/s^2%n", p, p.surfaceGravity());
}

Constant-specific method bodies

Declare an abstract method on the enum and give each constant its own implementation in a class body \{ …​ } after the constant. Each such constant becomes a compiler-generated anonymous subclass of the enum.

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);
}

// Operation.TIMES.apply(6, 7)  ->  42

A modern alternative — available since Java 8, so the pre-lambda books in this section’s bibliography show only the form above — is to store behaviour in a field as a lambda (see Lambdas and Method References):

import java.util.function.IntBinaryOperator;

public enum Operation {
    PLUS(Integer::sum),
    MINUS((a, b) -> a - b),
    TIMES((a, b) -> a * b),
    DIVIDE((a, b) -> a / b);

    private final IntBinaryOperator op;

    Operation(IntBinaryOperator op) {
        this.op = op;
    }

    public int apply(int a, int b) {
        return op.applyAsInt(a, b);
    }
}

IntBinaryOperator is one of the primitive functional interfaces in java.util.function.

EnumSet and EnumMap

java.util.EnumSet and java.util.EnumMap are Set and Map implementations specialised for enum keys. EnumSet is internally a bit vector (one long per 64 constants); EnumMap is backed by a plain array indexed by ordinal(). Both are far more compact and faster than HashSet / HashMap for this case (no hashing, no boxing, no buckets), and both iterate in the natural declaration order of the constants rather than hash order.

import java.util.EnumSet;

EnumSet<Day> workdays = EnumSet.range(Day.MONDAY, Day.FRIDAY);
EnumSet<Day> weekend  = EnumSet.complementOf(workdays);
EnumSet<Day> empty    = EnumSet.noneOf(Day.class);
EnumSet<Day> all      = EnumSet.allOf(Day.class);

System.out.println(workdays.contains(Day.WEDNESDAY)); // true
System.out.println(weekend);                          // [SATURDAY, SUNDAY]
import java.util.EnumMap;

EnumMap<Day, String> plan = new EnumMap<>(Day.class);
plan.put(Day.MONDAY, "on call");
plan.put(Day.SATURDAY, "off");

System.out.println(plan);   // {MONDAY=on call, SATURDAY=off}  -- declaration order

EnumSet has no public constructor — always use a factory such as of, range, allOf, noneOf, or complementOf. EnumMap needs the Class object so it can size its backing array up front. Neither is synchronized. Whenever a Set or Map is keyed purely by enum constants, prefer these over the hash-based collections. The Tutorials' Enum Types page introduces EnumSet alongside the language feature.

See Also

  • Records and Sealed Classes — the other restricted class forms, and sealed hierarchies as an open-ended alternative to a closed enum.

  • Pattern Matching — exhaustive switch over enums and sealed types without a default arm.

  • Collections Framework — where EnumSet and EnumMap sit among the Set and Map implementations.

  • Classes and Objects — fields, constructors, and methods, which enums reuse unchanged.