Enums — Type-Safe Constants with Fields, Methods, EnumMap, and EnumSet
In this tutorial, you will learn about Enums. We cover key concepts, practical examples, and best practices to help you master this topic.
Java enums provide type-safe constants that are more powerful than integer constants, supporting fields, methods, and specialized collections. Unlike public static final int constants, enums are full-featured classes — each constant is a Singleton instance of the enum type, with its own behavior and state.
What You'll Learn
- Declaring enums with fields, methods, and constructors
- Switching on enum values
EnumMapandEnumSetfor performant operations- Enum-specific behavior with abstract methods
Why It Matters
Enums prevent invalid constant usage. With int constants, any int value can be passed where a constant is expected. Enums restrict values to a fixed set at compile time, eliminating entire categories of bugs.
Real-World Use
HTTP status codes, days of the week, order states (NEW, PROCESSING, SHIPPED, DELIVERED), and configuration keys are all modeled as enums in production code.
Basic Enum Declaration
public enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Day today = Day.WEDNESDAY;
System.out.println(today); // WEDNESDAY
Enums are implicitly final, extend java.lang.Enum, and cannot be extended.
Enums with Fields and Methods
public enum Planet {
MERCURY(3.303e23, 2.4397e6),
VENUS(4.869e24, 6.0518e6),
EARTH(5.976e24, 6.37814e6),
MARS(6.421e23, 3.3972e6);
private final double mass;
private final double radius;
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
public double getMass() { return mass; }
public double getRadius() { return radius; }
public double surfaceGravity() {
return 6.67300e-11 * mass / (radius * radius);
}
}
Usage:
Planet earth = Planet.EARTH;
System.out.println(earth.surfaceGravity());
The constructor is private by default — you cannot create enum instances with new.
Abstract Methods in Enums
Each constant can implement its own behavior:
public enum Operation {
PLUS {
@Override
public double apply(double x, double y) {
return x + y;
}
},
MINUS {
@Override
public double apply(double x, double y) {
return x - y;
}
},
TIMES {
@Override
public double apply(double x, double y) {
return x * y;
}
},
DIVIDE {
@Override
public double apply(double x, double y) {
return x / y;
}
};
public abstract double apply(double x, double y);
}
Each constant provides its own implementation of the abstract method.
Switch with Enums
OrderStatus status = OrderStatus.SHIPPED;
switch (status) {
case NEW:
System.out.println("Order just placed");
break;
case PROCESSING:
System.out.println("Order is being prepared");
break;
case SHIPPED:
System.out.println("Order is on the way");
break;
case DELIVERED:
System.out.println("Order completed");
break;
}
Switch expressions work particularly well with enums since they are often exhaustive:
String message = switch (status) {
case NEW -> "Order just placed";
case PROCESSING -> "Order is being prepared";
case SHIPPED -> "Order is on the way";
case DELIVERED -> "Order completed";
};
Methods Inherited from Enum
Every enum inherits from java.lang.Enum:
Day d = Day.MONDAY;
d.name(); // "MONDAY"
d.ordinal(); // 0 (position in declaration)
d.compareTo(Day.TUESDAY); // negative (MONDAY < TUESDAY)
d.toString(); // "MONDAY"
// Static methods added by compiler
Day.valueOf("MONDAY"); // Day.MONDAY
Day.values(); // Day[]{MONDAY, TUESDAY, ...}
EnumMap
EnumMap is a specialized Map implementation for enum keys. It is ordered by the enum's natural order (ordinal) and is more efficient than HashMap:
Map<Day, String> schedule = new EnumMap<>(Day.class);
schedule.put(Day.MONDAY, "Meeting at 10am");
schedule.put(Day.FRIDAY, "Team standup at 9am");
for (Day d : schedule.keySet()) {
System.out.println(d + ": " + schedule.get(d));
}
EnumMap uses an internal array indexed by ordinal, so get and put are O(1) and very fast.
EnumSet
EnumSet is a specialized Set implementation for enum elements:
Set<Day> weekend = EnumSet.of(Day.SATURDAY, Day.SUNDAY);
Set<Day> workWeek = EnumSet.range(Day.MONDAY, Day.FRIDAY);
Set<Day> allDays = EnumSet.allOf(Day.class);
Set<Day> empty = EnumSet.noneOf(Day.class);
EnumSet is backed by a bit vector and is extremely memory-efficient and fast.
Common Mistakes
- Using
ordinal()to store enum order in a database. The ordinal depends on declaration order — reordering constants breaks the mapping. Storename()instead. - Adding too many responsibilities to an enum. Enums are constants, not full service classes. Keep behavior focused on the constant's immediate purpose.
- Forgetting that enum constructors are implicitly private. You cannot instantiate enums with
new. - Using
==instead of.equals()for enums. Both work because each constant is a singleton, but==is slightly faster and is the idiomatic comparison for enums. - Using
HashMap<Enum, ...>instead ofEnumMap.EnumMapis faster and more memory-efficient.
Practice Questions
1. Can an enum have a constructor?
Yes, but it must be private (implicitly or explicitly). The constructor is called once per constant at class initialization.
2. What is the difference between name() and toString() on an enum?
name() is final and always returns the exact declaration name. toString() is not final and can be overridden to return a user-friendly representation.
3. Why is EnumMap more efficient than HashMap for enum keys?
EnumMap uses an array indexed by ordinal, so lookups are O(1) array access with no hashing overhead.
4. Can an enum implement an interface?
Yes. Enums can implement interfaces but cannot extend other classes (they already extend Enum).
5. What happens if you switch on an enum and forget a case?
The code compiles. At runtime, if an unhandled value is encountered, no case matches and execution continues after the switch. Switch expressions, however, require exhaustiveness.
Challenge Question:
Design a TrafficLight enum with constants RED, YELLOW, GREEN. Add a method next() that returns the next light in the cycle. Use an abstract method so each constant defines its own next(). Also create an EnumMap<TrafficLight, String> with duration descriptions.
FAQ
Mini Project
Write a program EnumDemo.java that:
- Defines an
HttpStatusenum with constants likeOK(200),NOT_FOUND(404),INTERNAL_SERVER_ERROR(500)— each with a code and description - Adds a method
isSuccess(),isClientError(),isServerError() - Creates an
EnumMap<HttpStatus, String>mapping status codes to response messages - Creates an
EnumSetof all 2xx success codes and all 4xx client error codes - Shows that
EnumSet.range()works correctly with ordinal ordering - Writes a command-line program that takes a status code number and returns the enum constant using a static
fromCode(int)method
What's Next
Enums give you fixed sets of constants. But what about simple data carriers that just hold values? Lesson 19 introduces records (Java 14+) — compact data carriers that eliminate boilerplate and provide equals, hashCode, and toString automatically.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro