Enums in Java
Introduction
Before Java 5, developers often relied on public static final integer or string constants to represent a fixed set of values (e.g., days of the week, states of a process). This approach was deeply flawed: it lacked type safety, provided no namespace configuration, and often led to cryptic runtime errors.
Enter Enums (short for Enumerations). An enum is a special data type that enables a variable to be a set of predefined constants. More than just a simple list of values, Java enums are full-fledged classes under the hood, allowing them to have fields, methods, and constructors.
The Basics of Enums
An enum is defined using the enum keyword.
public enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Usage in Code
Because enums are strongly typed, the compiler ensures that only valid enum values are assigned to variables of that type.
public class Schedule {
public static void main(String[] args) {
Day today = Day.WEDNESDAY;
if (today == Day.WEDNESDAY) {
System.out.println("Halfway through the work week!");
}
// Using enums in a switch statement (highly recommended)
switch (today) {
case MONDAY:
System.out.println("Start of the week.");
break;
case FRIDAY:
System.out.println("End of the work week.");
break;
case SATURDAY:
case SUNDAY:
System.out.println("Weekend!");
break;
default:
System.out.println("Midweek day.");
break;
}
}
}
Advanced Enum Capabilities
Unlike C/C++ where enums are essentially integers, Java enums are compiled into classes that extend java.lang.Enum. This unlocks powerful capabilities.
1. Enums with Fields, Constructors, and Methods
You can associate data and behavior with each enum constant.
public enum CoffeeSize {
SMALL(250),
MEDIUM(350),
LARGE(500); // Semicolon required when fields/methods follow
private final int milliliters; // Field
// Constructor (Must be private or package-private)
CoffeeSize(int milliliters) {
this.milliliters = milliliters;
}
// Getter method
public int getMilliliters() {
return this.milliliters;
}
}
2. Enums Implementing Interfaces
Enums can implement interfaces, allowing them to be used polymorphically.
public interface Operation {
double apply(double x, double y);
}
public enum BasicMath implements Operation {
PLUS("+") {
public double apply(double x, double y) { return x + y; }
},
MINUS("-") {
public double apply(double x, double y) { return x - y; }
},
MULTIPLY("*") {
public double apply(double x, double y) { return x * y; }
},
DIVIDE("/") {
public double apply(double x, double y) { return x / y; }
};
private final String symbol;
BasicMath(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
}
Here, each enum constant provides a specific implementation of the apply method, illustrating the Strategy pattern encapsulated cleanly within an enum.
Internal Mechanics & Built-in Methods
When you compile an enum, the JVM automatically generates several useful methods:
values(): Returns an array containing all of the values of the enum in the order they are declared. Extremely useful for iteration.for (Day d : Day.values()) { System.out.println(d); }valueOf(String name): Returns the enum constant of the specified string type. The string must match exactly.Day d = Day.valueOf("MONDAY");name(): Returns the exact string name of the constant.ordinal(): Returns the position of the constant in the enum declaration, starting from 0. (Note: Avoid tying business logic to ordinals, as reordering the enum will break the logic).
EnumSet and EnumMap
Java provides highly optimized collection implementations specifically for enums:
EnumSet: A specialized Set implementation that uses a bit-vector internally. It is extremely fast and compact.EnumMap: A specialized Map implementation where keys are enum constants. It uses arrays internally for blazing-fast lookups.
EnumSet<Day> weekend = EnumSet.of(Day.SATURDAY, Day.SUNDAY);
EnumMap<Day, String> schedule = new EnumMap<>(Day.class);
schedule.put(Day.MONDAY, "Gym");
Summary
Enums in Java are a robust tool for representing a fixed domain of values. By leveraging their class-like capabilities—adding fields, methods, and implementing interfaces—you can encapsulate behavior directly alongside the constants, leading to highly cohesive, type-safe, and expressive code.