Enums

Beginner
OOP & Advanced Classes

Replace magic constants with type-safe enums that can carry fields, methods, and even abstract methods per constant.

Overview

An enum (enumeration) is a special class whose instances are a fixed set of named constants. Enums are far superior to int constants or String constants: they are type-safe (you can't pass an invalid value), self-documenting, and support switch. Java enums are full classes — they can have fields, constructors, methods, and even implement interfaces. Each constant can override methods individually. EnumSet and EnumMap provide highly efficient collections backed by bit vectors.

Basic Enums & Built-in Methods

Every enum constant is an instance of the enum class. Built-in methods: name() returns the constant's name as a String, ordinal() returns its zero-based position, values() returns all constants in declaration order, and valueOf(String) returns the constant for a given name (throws IllegalArgumentException if not found).

Enums work seamlessly with switch. In switch expressions (Java 14+) the compiler can check that all cases are covered.

EnumBasics.java
public enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;

    public boolean isWeekend() {
        return this == SATURDAY || this == SUNDAY;
    }
}

public class EnumBasics {
    public static void main(String[] args) {
        Day today = Day.WEDNESDAY;

        System.out.println(today.name());    // WEDNESDAY
        System.out.println(today.ordinal()); // 2 (zero-based)
        System.out.println(today.isWeekend()); // false

        // Iterate all constants
        for (Day d : Day.values()) {
            System.out.print(d + " ");
        }
        System.out.println();

        // Parse from String
        Day friday = Day.valueOf("FRIDAY");
        System.out.println(friday.isWeekend()); // false

        // Switch expression — compiler verifies exhaustiveness
        String type = switch (today) {
            case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Weekday";
            case SATURDAY, SUNDAY -> "Weekend";
        };
        System.out.println(type);  // Weekday
    }
}

Enums with Fields & Methods

Each enum constant can carry data by defining fields and a constructor. The constructor is always private (or package-private) — you cannot call new Planet() externally. Define methods on the enum to compute values from the fields.

For per-constant behaviour, each constant can override a method defined as abstract in the enum body — essentially giving each constant its own implementation.

Planet.java / Operation.java
public enum Planet {
    MERCURY(3.303e+23, 2.4397e6),
    VENUS  (4.869e+24, 6.0518e6),
    EARTH  (5.976e+24, 6.37814e6),
    MARS   (6.421e+23, 3.3972e6);

    private final double mass;    // in kilograms
    private final double radius;  // in metres

    // Enum constructor — implicitly private
    Planet(double mass, double radius) {
        this.mass   = mass;
        this.radius = radius;
    }

    static final double G = 6.67300E-11;

    public double surfaceGravity() {
        return G * mass / (radius * radius);
    }

    public double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }

    public static void main(String[] args) {
        double earthWeight = 75.0;
        double mass = earthWeight / EARTH.surfaceGravity();
        for (Planet p : values()) {
            System.out.printf("Weight on %-8s = %6.2f N%n", p, p.surfaceWeight(mass));
        }
    }
}

// Per-constant behaviour with abstract method
enum Operation {
    ADD("+")  { @Override public double apply(double x, double y) { return x + y; } },
    SUB("-")  { @Override public double apply(double x, double y) { return x - y; } },
    MUL("*")  { @Override public double apply(double x, double y) { return x * y; } },
    DIV("/")  { @Override public double apply(double x, double y) { return x / y; } };

    private final String symbol;
    Operation(String symbol) { this.symbol = symbol; }

    public abstract double apply(double x, double y);

    @Override public String toString() { return symbol; }
}

EnumSet & EnumMap

EnumSet is a specialised Set implementation for enum types. Internally it uses a single long bit-vector — making contains(), add(), and iteration O(1) with zero object overhead. Always prefer EnumSet over HashSet<MyEnum>.

EnumMap is a Map implementation whose keys are enum constants. It is backed by a simple array indexed by ordinal — faster and more memory-efficient than HashMap<MyEnum, V>.

Enums also make excellent singletons — the JVM guarantees each constant is instantiated exactly once.

EnumCollections.java
import java.util.EnumSet;
import java.util.EnumMap;

public class EnumCollections {
    enum Permission { READ, WRITE, EXECUTE, DELETE }

    public static void main(String[] args) {
        // EnumSet — backed by bit vector, extremely fast
        EnumSet<Permission> adminPerms = EnumSet.allOf(Permission.class);
        EnumSet<Permission> userPerms  = EnumSet.of(Permission.READ, Permission.WRITE);
        EnumSet<Permission> readOnly   = EnumSet.of(Permission.READ);

        System.out.println(adminPerms.contains(Permission.DELETE)); // true
        System.out.println(userPerms.contains(Permission.DELETE));  // false

        // Set operations
        EnumSet<Permission> extra = EnumSet.copyOf(adminPerms);
        extra.removeAll(userPerms);
        System.out.println(extra);  // [EXECUTE, DELETE]

        // EnumMap — array-backed, ordered by ordinal
        EnumMap<Permission, String> descriptions = new EnumMap<>(Permission.class);
        descriptions.put(Permission.READ,    "Can view files");
        descriptions.put(Permission.WRITE,   "Can modify files");
        descriptions.put(Permission.EXECUTE, "Can run programs");
        descriptions.put(Permission.DELETE,  "Can remove files");

        userPerms.forEach(p -> System.out.println(p + ": " + descriptions.get(p)));

        // Enum as singleton — thread-safe, serialisation-safe
        Singleton s1 = Singleton.INSTANCE;
        Singleton s2 = Singleton.INSTANCE;
        System.out.println(s1 == s2);  // true — always same instance
    }
}

enum Singleton {
    INSTANCE;
    private int count = 0;
    public void increment() { count++; }
    public int getCount()   { return count; }
}

Key Points to Remember

  • Enum constants are instances of the enum class — fully type-safe, no invalid values possible
  • Enum constructors are implicitly private; values(), ordinal(), name(), valueOf() are built-in
  • Enums with abstract methods let each constant carry its own behaviour
  • EnumSet uses a bit-vector internally — always prefer over HashSet<YourEnum>
  • EnumMap is array-backed by ordinal — faster than HashMap<YourEnum, V>
  • Enums are the best Singleton implementation: thread-safe and serialisation-safe by the JVM spec

Practice Enums in the Playground

Run and modify code directly in your browser - no setup needed.

Interview Questions

Sign in to ask Aria
1

Can an enum have a constructor? Can you call new on an enum?

EasyTCS
2

What is the difference between EnumSet and HashSet?

MediumAmazon
3

How do you implement the Singleton pattern using an enum?

MediumGoogle
4

Can an enum implement an interface in Java?

EasyOracle
5

What is the difference between ordinal() and name() in an enum?

EasyWipro

Ask Aria about Enums

Your personal AI tutor — ask anything about this concept