Java Enum — Type-Safe Constants with Fields, Methods & More
An enum (short for enumeration) is a special Java type used to define a fixed set of constants. Unlike plain static final fields, enums are type-safe, can have fields and methods, and work beautifully with switch.
Why Enums?
Before Enums (The Problem)
// BAD — magic numbers
public static final int STATUS_PENDING = 0;
public static final int STATUS_APPROVED = 1;
public static final int STATUS_REJECTED = 2;
void process(int status) { ... } // any int is accepted!
process(42); // compiles but makes no sense
With Enums (The Solution)
public enum Status {
PENDING, APPROVED, REJECTED
}
void process(Status status) { ... }
process(Status.APPROVED); // ✅ type-safe
process(42); // ❌ compile error
Declaring Enums
public enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY,
FRIDAY, SATURDAY, SUNDAY
}
Each constant is a public static final instance of the enum.
Day today = Day.FRIDAY;
System.out.println(today); // FRIDAY
System.out.println(today.name()); // FRIDAY
System.out.println(today.ordinal()); // 4 (zero-based position)
Enums in switch
Day day = Day.SATURDAY;
switch (day) {
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY ->
System.out.println("Weekday");
case SATURDAY, SUNDAY ->
System.out.println("Weekend!");
}
In
switch, you writeMONDAY, notDay.MONDAY.
values() and valueOf()
// Iterate all constants
for (Day d : Day.values()) {
System.out.println(d);
}
// Convert from String
Day monday = Day.valueOf("MONDAY"); // MONDAY
Day bad = Day.valueOf("FUNDAY"); // IllegalArgumentException
Enums with Fields, Constructors, and Methods
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; // kg
private final double radius; // metres
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
public double getMass() { return mass; }
public double getRadius() { return radius; }
// Surface gravity: G * mass / radius²
public double surfaceGravity() {
return 6.67300E-11 * mass / (radius * radius);
}
// Weight on this planet
public double surfaceWeight(double otherMass) {
return otherMass * surfaceGravity();
}
}
double earthWeight = 75.0;
double mass = earthWeight / Planet.EARTH.surfaceGravity();
for (Planet p : Planet.values()) {
System.out.printf("Weight on %s: %.2f%n", p, p.surfaceWeight(mass));
}
Important: Enum constructors are always
private(you can omit the keyword).
Enum Implementing Interfaces
public interface Describable {
String describe();
}
public enum Season implements Describable {
SPRING { public String describe() { return "Flowers bloom"; } },
SUMMER { public String describe() { return "Sun shines"; } },
AUTUMN { public String describe() { return "Leaves fall"; } },
WINTER { public String describe() { return "Snow falls"; } };
}
Or with a shared implementation:
public enum Priority implements Comparable<Priority> {
LOW(1), MEDIUM(5), HIGH(10);
private final int level;
Priority(int level) { this.level = level; }
public int getLevel() { return level; }
}
Abstract Methods in Enums
public enum Operation {
ADD {
public double apply(double a, double b) { return a + b; }
},
SUBTRACT {
public double apply(double a, double b) { return a - b; }
},
MULTIPLY {
public double apply(double a, double b) { return a * b; }
},
DIVIDE {
public double apply(double a, double b) { return a / b; }
};
public abstract double apply(double a, double b);
}
// Usage
double result = Operation.ADD.apply(3, 4); // 7.0
EnumSet — High-Performance Set for Enums
import java.util.EnumSet;
EnumSet<Day> weekend = EnumSet.of(Day.SATURDAY, Day.SUNDAY);
EnumSet<Day> weekdays = EnumSet.complementOf(weekend);
EnumSet<Day> all = EnumSet.allOf(Day.class);
EnumSet<Day> none = EnumSet.noneOf(Day.class);
weekend.contains(Day.SUNDAY) // true
Internally implemented as a bit vector — extremely fast and memory-efficient.
EnumMap — Map Keyed by Enum
import java.util.EnumMap;
EnumMap<Day, String> schedule = new EnumMap<>(Day.class);
schedule.put(Day.MONDAY, "Gym");
schedule.put(Day.FRIDAY, "Movie night");
System.out.println(schedule.get(Day.MONDAY)); // "Gym"
More efficient than HashMap when keys are enums.
Singleton Pattern with Enum
The simplest and safest way to implement a singleton in Java:
public enum Database {
INSTANCE;
private final Connection connection;
Database() {
connection = createConnection();
}
public Connection getConnection() {
return connection;
}
private Connection createConnection() {
// ... create and return connection
return null;
}
}
// Usage
Database.INSTANCE.getConnection();
This is thread-safe, serialisation-safe, and reflection-proof — something other singleton patterns cannot guarantee.
Common Mistakes
| Mistake | Problem | Fix |
|---|---|---|
Comparing enums with .equals() |
Works but unnecessary | Use == (enums are singletons) |
Using ordinal() for logic |
Breaks when order changes | Use fields instead |
| Mutable fields in enums | Shared state, thread issues | Make fields final |
Using valueOf() without try-catch |
IllegalArgumentException on bad input |
Validate or catch |
// GOOD — safe valueOf
public static Optional<Day> fromString(String name) {
try {
return Optional.of(Day.valueOf(name.toUpperCase()));
} catch (IllegalArgumentException e) {
return Optional.empty();
}
}
Key Takeaways
- Enums provide type-safe constants — far better than
intorStringconstants. - Enums can have fields, constructors, and methods.
- Use
EnumSetandEnumMapfor high-performance enum collections. - Compare enums with
==, not.equals(). - Enum is the best singleton pattern in Java.
What’s Next?
Next: Java Math Class — Math.abs(), Math.random(), Math.pow(), and the Random class.