Enums
Enums (short for enumerations) give you a clean, type-safe way to represent a fixed set of named constants — think days of the week, compass directions, or order statuses. Unlike plain int or String constants, an enum makes illegal values impossible at compile time.
Why Use Enums?
Before enums (introduced in Java 5), developers often wrote constants like this:
// Old pattern — error-prone int flags
public static final int STATUS_NEW = 0;
public static final int STATUS_ACTIVE = 1;
public static final int STATUS_INACTIVE = 2;
Nothing stops a caller from passing 99 where only 0–2 make sense. Enums eliminate that entire class of bug by making the type itself the constraint.
Declaring a Basic Enum
Use the enum keyword instead of class:
public enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Each identifier (MONDAY, TUESDAY, …) is a constant — an instance of the Day type. By convention, enum constants are written in UPPER_SNAKE_CASE.
Using an Enum
public class Main {
public static void main(String[] args) {
Day today = Day.WEDNESDAY;
System.out.println(today); // WEDNESDAY
System.out.println(today.ordinal()); // 2 (zero-based index)
System.out.println(today.name()); // WEDNESDAY
}
}
Output:
WEDNESDAY
2
WEDNESDAY
Enums in a switch Statement
Enums pair naturally with switch:
Day day = Day.SATURDAY;
switch (day) {
case SATURDAY:
case SUNDAY:
System.out.println("Weekend!");
break;
default:
System.out.println("Weekday.");
}
Output:
Weekend!
With modern switch expressions (Java 14+), this becomes even cleaner:
String type = switch (day) {
case SATURDAY, SUNDAY -> "Weekend";
default -> "Weekday";
};
System.out.println(type); // Weekend
Built-in Enum Methods
Every enum automatically inherits several useful methods:
| Method | Description |
|---|---|
name() | Returns the constant’s declared name as a String |
ordinal() | Returns the zero-based position in the declaration |
toString() | Same as name() by default (can be overridden) |
Day.values() | Returns an array of all constants in declaration order |
Day.valueOf("MONDAY") | Returns the constant matching the given string |
// Iterating all constants
for (Day d : Day.values()) {
System.out.println(d.ordinal() + " -> " + d);
}
Output:
0 -> MONDAY
1 -> TUESDAY
2 -> WEDNESDAY
3 -> THURSDAY
4 -> FRIDAY
5 -> SATURDAY
6 -> SUNDAY
Tip: Use
Day.valueOf("FRIDAY")when you need to convert a user-provided string back to an enum. It throwsIllegalArgumentExceptionif the string doesn’t match any constant, so wrap it in a try-catch or validate first.
Enums with Fields and Constructors
Here is where enums really shine: each constant can carry its own data.
public enum Planet {
MERCURY(3.303e+23, 2.4397e6),
VENUS (4.869e+24, 6.0518e6),
EARTH (5.976e+24, 6.37814e6);
private final double mass; // in kilograms
private final double radius; // in metres
// Enum constructor — always implicitly private
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
double surfaceGravity() {
final double G = 6.67300E-11;
return G * mass / (radius * radius);
}
}
System.out.printf("Earth gravity: %.2f m/s²%n", Planet.EARTH.surfaceGravity());
Output:
Earth gravity: 9.80 m/s²
Note: Enum constructors are always private (or package-private, which Java silently makes private). You cannot call
new Planet(...)yourself — the JVM creates the instances once, at class-loading time.
Enums with Abstract Methods
You can declare an abstract method inside an enum and override it per constant — a compact form of the Strategy pattern:
public enum Operation {
ADD {
@Override
public int apply(int a, int b) { return a + b; }
},
SUBTRACT {
@Override
public int apply(int a, int b) { return a - b; }
},
MULTIPLY {
@Override
public int apply(int a, int b) { return a * b; }
};
public abstract int apply(int a, int b);
}
System.out.println(Operation.ADD.apply(10, 3)); // 13
System.out.println(Operation.SUBTRACT.apply(10, 3)); // 7
System.out.println(Operation.MULTIPLY.apply(10, 3)); // 30
Output:
13
7
30
Implementing Interfaces
Enums can implement interfaces — they just cannot extend a class (they already implicitly extend java.lang.Enum).
interface Describable {
String describe();
}
public enum Season implements Describable {
SPRING, SUMMER, AUTUMN, WINTER;
@Override
public String describe() {
return "Season: " + name();
}
}
System.out.println(Season.SUMMER.describe()); // Season: SUMMER
EnumSet and EnumMap
The java.util package ships two highly efficient collections built specifically for enums:
EnumSet— aSetbacked by a bit vector; blazing fast for membership checksEnumMap— aMapwith enum keys; more compact thanHashMap
import java.util.EnumSet;
EnumSet<Day> weekend = EnumSet.of(Day.SATURDAY, Day.SUNDAY);
System.out.println(weekend.contains(Day.SATURDAY)); // true
System.out.println(weekend.contains(Day.MONDAY)); // false
See the dedicated EnumSet & EnumMap page for full coverage.
Under the Hood
When the Java compiler encounters an enum, it generates a regular class that:
- Extends
java.lang.Enum<E>— giving youname(),ordinal(),compareTo(), andequals()/hashCode()for free. - Declares each constant as a
public static finalfield of the enum’s own type, initialized in astatic {}block. - Creates a hidden
$VALUESarray thatvalues()clones and returns.
You can verify this with the javap tool:
javap -p Day.class
The output will show something like:
public static final Day MONDAY;
public static final Day TUESDAY;
...
private static final Day[] $VALUES;
static {};
Because each constant is a singleton created at class-load time, enum-based singletons are thread-safe by default — a popular pattern in effective Java design. Enum serialization is also safe: the JVM guarantees that deserialization returns the existing singleton rather than creating a new instance.
Warning: Rely on
name()or an explicit field for persistence (databases, files, APIs) — never onordinal(). Inserting a new constant in the middle of an enum will shift all subsequent ordinals and silently corrupt stored data.
Comparing Enums
Use == to compare enum values, not .equals(). Because every constant is a singleton, == is both safe and slightly faster:
Day d = Day.FRIDAY;
System.out.println(d == Day.FRIDAY); // true
System.out.println(d.equals(Day.FRIDAY)); // also true, but == is preferred
Quick Reference
| Feature | Supported? |
|---|---|
| Fields | Yes |
| Constructors (public/protected) | No — always private |
| Instance methods | Yes |
| Abstract methods | Yes |
| Implement interface | Yes |
| Extend a class | No (already extends java.lang.Enum) |
| Used in switch | Yes |
| Serializable | Yes (built-in) |
Related Topics
- Switch Expressions — pattern-match over enums with concise arrow syntax in Java 14+
- EnumSet & EnumMap — high-performance collections designed for enum keys and values
- Static Keyword — understand why enum constants are implicitly
public static final - Interfaces — enums can implement interfaces to add polymorphic behavior
- Serialization — how enum singletons survive object serialization safely
- Pattern Matching — combine enums with sealed types and pattern matching in Java 21