enum Direction {
NORTH, SOUTH, EAST, WEST
}Java Enums: Type-Safe Enumerations, Fields, Methods, and Interfaces
Direct Answer & Core Concept
Java enum is a special type used to represent a fixed set of named constants. Instead of using arbitrary integers or strings for values such as days, statuses, directions, or user roles, an enum gives those values a clear and type-safe representation.
Java enums can do much more than simply store constants. An enum can have fields, constructors, methods, interfaces, and even constant-specific behavior. Because an enum is a real Java type, it can also be used with collections, switch statements, and generic APIs.
In this tutorial, you will learn how to create enums, access enum constants, use fields and methods, define constructors, implement interfaces, compare enum values, use enums with switch, and work with EnumSet and EnumMap.
Detailed Explanation & Mechanics
What Is an Enum in Java?
An enum, short for enumeration, defines a restricted set of predefined values.
For example:
The Direction type can contain only the constants defined by the enum.
You can create a variable like this:
Direction direction = Direction.NORTH;This is safer than representing directions with arbitrary strings:
String direction = "north";With a String, values such as "North", "NORTH", "north", or "Nroth" can accidentally appear. An enum restricts the value to the defined constants.
Why Use Enums?
Enums are useful when a variable should have one value from a known, fixed set.
Common examples include:
Days of the week
Months
Order status
Payment status
User roles
Directions
Access levels
HTTP-like application states
Priority levels
Traffic-light states
For example:
enum OrderStatus {
PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED
}Now an order can use:
OrderStatus status = OrderStatus.SHIPPED;This makes the possible states explicit in the type itself.
Basic Enum Syntax
The simplest enum declaration looks like this:
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}You can then use:
Day today = Day.MONDAY;
System.out.println(today);Output:
MONDAYEach constant is an instance of the enum type.
Enum Constants
The values inside an enum are called enum constants.
For:
enum Size {
SMALL, MEDIUM, LARGE
}the constants are:
Size.SMALLSize.MEDIUMSize.LARGEThey are not ordinary string values.
For example:
Size size = Size.SMALL;The variable size has type Size.
Enum Values Are Type-Safe
Consider:
enum Priority {
LOW, MEDIUM, HIGH
}This is valid:
Priority priority = Priority.HIGH;But this is not:
Priority priority = "HIGH";The string "HIGH" and the enum constant Priority.HIGH are different types.
This compile-time type checking is one of the major benefits of enums.
Enum With a switch Statement
Enums work naturally with switch.
enum Day {
MONDAY, TUESDAY, WEDNESDAY
}public class Main {
public static void main(String[] args) {
Day day = Day.MONDAY;
switch (day) {
case MONDAY: System.out.println("Start of the week");
break;
case TUESDAY: System.out.println("Tuesday");
break;
case WEDNESDAY: System.out.println("Wednesday");
break;
}
}
}Inside the switch, you normally write the enum constant directly rather than repeating the enum type.
Modern Switch Expressions With Enums
Modern Java also supports switch expressions.
enum Day {
MONDAY, TUESDAY, SATURDAY, SUNDAY
}public class Main {
public static void main(String[] args) {
Day day = Day.SATURDAY;
String type = switch (day) {
case SATURDAY, SUNDAY -> "Weekend";
default -> "Weekday";
};
System.out.println(type);
}
}Output:
WeekendSwitch expressions are often more concise when the goal is to produce a value.
The values() Method
Every enum provides a values() method that returns its constants.
Example:
enum Color {
RED, GREEN, BLUE
}public class Main {
public static void main(String[] args) {
for (Color color : Color.values()) {
System.out.println(color);
}
}
}Output:
REDGREENBLUEThis is useful when you need to iterate over all available enum constants.
The valueOf() Method
Enums also provide a valueOf() method for converting a matching string into an enum constant.
enum Status {
PENDING, APPROVED, REJECTED
}Then:
Status status = Status.valueOf("APPROVED");
System.out.println(status);Output:
APPROVEDThe string must match the enum constant name exactly.
For example:
Status.valueOf("approved");does not automatically perform case conversion.
It throws:
IllegalArgumentExceptionwhen no matching constant exists.
Using name() With Enums
Every enum constant has a name() method.
enum Status {
PENDING, APPROVED
}Status status = Status.APPROVED;
System.out.println(status.name());Output:
APPROVEDname() returns the exact declared enum constant name.
toString() and Enum Display
An enum also inherits behavior from Enum, including toString().
Normally:
System.out.println(Status.APPROVED);produces:
APPROVEDBut toString() can be overridden when a different display representation is required.
For example:
enum Status {
PENDING, APPROVED;
@Override public String toString() {
return name().toLowerCase();
}
}Now:
System.out.println(Status.APPROVED);can produce:
approvedUse this carefully when the enum's display form is part of an application's API or data format.
Enum Fields
An enum can contain fields just like a normal class.
For example:
enum Planet {
EARTH(5.97), MARS(0.642), JUPITER(1898.0);
private final double mass;
Planet(double mass) {
this.mass = mass;
} public double getMass() {
return mass;
}
}Now:
System.out.println(Planet.EARTH.getMass());Output:
5.97This makes enums useful for representing constants that have associated data.
Enum Constructors
Enums can have constructors.
Example:
enum Level {
LOW(1), MEDIUM(2), HIGH(3);
private final int code;
Level(int code) {
this.code = code;
} public int getCode() {
return code;
}
}Each constant passes its value to the enum constructor:
LOW → 1MEDIUM → 2HIGH → 3Enum constructors are not called directly with new.
You cannot write:
new Level(1);Enum instances are controlled by the enum type itself.
Enum Constructors Are Effectively Private
Enum constructors cannot be invoked from outside the enum.
For example:
enum Status {
ACTIVE, INACTIVE;
Status() {
System.out.println("Constructor called");
}
}The enum system creates the constants.
You use:
Status.ACTIVErather than constructing a new Status.
Enum Methods
Enums can contain methods.
enum TrafficLight {
RED, YELLOW, GREEN;
public boolean allowsDriving() {
return this == GREEN;
}
}Usage:
TrafficLight light = TrafficLight.GREEN;
System.out.println( light.allowsDriving());Output:
trueThis allows behavior to be associated directly with the enum type.
Enum With Fields and Methods
Here is a complete example:
enum OrderStatus {
PENDING("Order received"), SHIPPED("Order shipped"), DELIVERED("Order delivered"), CANCELLED("Order cancelled");
private final String message;
OrderStatus(String message) {
this.message = message;
} public String getMessage() {
return message;
}
}Usage:
OrderStatus status = OrderStatus.SHIPPED;
System.out.println(status.getMessage());Output:
Order shippedThis is a common pattern for giving enum constants additional application-specific information.
Enum Implementing an Interface
An enum can implement one or more interfaces.
Example:
interface Describable {
String getDescription();
}enum Priority implements Describable {
LOW, MEDIUM, HIGH;
@Override public String getDescription() {
return "Priority: " + name();
}
}Usage:
Priority priority = Priority.HIGH;
System.out.println( priority.getDescription());Output:
Priority: HIGHThis is useful when enum constants need to follow a common contract.
Enum With an Interface and Fields
A more practical example:
interface CodeProvider {
int getCode();
}enum PaymentStatus implements CodeProvider {
PENDING(100), SUCCESS(200), FAILED(500);
private final int code;
PaymentStatus(int code) {
this.code = code;
} @Override public int getCode() {
return code;
}
}Usage:
PaymentStatus status = PaymentStatus.SUCCESS;
System.out.println(status.getCode());Output:
200The enum now combines:
Fixed constants
Associated data
A method
An interface contract
Constant-Specific Enum Behavior
Each enum constant can have its own implementation of an abstract method.
Example:
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);
}Usage:
System.out.println( Operation.ADD.apply(10, 5));
System.out.println( Operation.MULTIPLY.apply(10, 5));Output:
1550This technique allows each constant to provide different behavior while keeping everything inside one enum type.
Comparing Enum Values
The recommended way to compare enum constants is normally ==.
Example:
enum Status {
ACTIVE, INACTIVE
}Status status = Status.ACTIVE;
if (status == Status.ACTIVE) {
System.out.println("Active");
}Enum constants are unique instances within their enum type, making identity comparison appropriate.
You can also use:
status.equals(Status.ACTIVE)but == is simple and avoids concerns about a null receiver.
For example:
if (status == Status.ACTIVE) {
// ...
}is safe even when status is null; it simply evaluates to false.
Enum and ordinal()
Every enum constant has an ordinal position.
Example:
enum Size {
SMALL, MEDIUM, LARGE
}Then:
System.out.println(Size.SMALL.ordinal());
System.out.println(Size.MEDIUM.ordinal());
System.out.println(Size.LARGE.ordinal());Output:
012The first constant has ordinal 0.
Should You Store ordinal() in a Database?
Generally, no.
Do not use:
Size.SMALL.ordinal()as a persistent business identifier unless you deliberately control the consequences.
If the enum changes:
enum Size {
SMALL, MEDIUM, LARGE
}and later becomes:
enum Size {
EXTRA_SMALL, SMALL, MEDIUM, LARGE
}the ordinal values shift.
Instead, use an explicit field:
enum Size {
SMALL(10), MEDIUM(20), LARGE(30);
private final int code;
Size(int code) {
this.code = code;
} public int getCode() {
return code;
}
}Now the application controls the business codes explicitly.
Enum With Custom Codes
This is a common real-world pattern:
enum Country {
INDIA("IN"), UNITED_STATES("US"), UNITED_KINGDOM("GB");
private final String code;
Country(String code) {
this.code = code;
} public String getCode() {
return code;
}
}Usage:
System.out.println( Country.INDIA.getCode());Output:
INThis is preferable to relying on ordinal positions when the value needs to remain stable.
Enum With a Lookup Method
You can create a method that finds an enum constant from an external code.
enum Country {
INDIA("IN"), UNITED_STATES("US"), UNITED_KINGDOM("GB");
private final String code;
Country(String code) {
this.code = code;
} public String getCode() {
return code;
} public static Country fromCode(String code) {
for (Country country : values()) {
if (country.code.equals(code)) {
return country;
}
} throw new IllegalArgumentException( "Unknown country code: " + code);
}
}Usage:
Country country = Country.fromCode("IN");
System.out.println(country);Output:
INDIAFor a small enum, this simple loop is often perfectly adequate.
Enum and Null Values
An enum variable can contain null because it is a reference type.
For example:
Status status = null;But calling:
status.name();causes:
NullPointerExceptionAlways consider whether an enum variable can be null.
If a value should always exist, enforce that rule through your application's design.
Enum as a Method Parameter
Enums work well as method parameters because they restrict callers to valid values.
enum PaymentMethod {
CASH, CARD, UPI
}public static void pay( PaymentMethod method) {
System.out.println( "Payment method: " + method);
}Call:
pay(PaymentMethod.UPI);This is clearer than:
pay("upi");because the compiler knows which values are allowed.
Enum as a Method Return Type
An enum can also be returned from methods.
enum UserStatus {
ACTIVE, BLOCKED, DELETED
}public static UserStatus getStatus() {
return UserStatus.ACTIVE;
}This gives callers a well-defined set of possible results.
Enum With EnumSet
Java provides a specialized collection called EnumSet for enum values.
Example:
import java.util.EnumSet;
enum Permission {
READ, WRITE, DELETE, EXECUTE
}Create a set:
EnumSet<Permission> permissions = EnumSet.of( Permission.READ, Permission.WRITE);Then:
System.out.println(permissions);EnumSet is designed specifically for enum elements and is often more efficient and expressive than using a general-purpose Set for the same purpose.
Useful EnumSet Operations
EnumSet<Permission> all = EnumSet.allOf(Permission.class);This creates a set containing all enum constants.
You can also create an empty set:
EnumSet<Permission> none = EnumSet.noneOf(Permission.class);And create a range for enums that have a natural declaration order:
EnumSet<Permission> range = EnumSet.range( Permission.READ, Permission.DELETE);Use ranges carefully because they follow enum declaration order, not a separate business ordering.
Enum With EnumMap
EnumMap is a specialized map designed for enum keys.
Example:
import java.util.EnumMap;
enum Department {
HR, IT, SALES
}EnumMap<Department, String> managers = new EnumMap<>(Department.class);
managers.put(Department.HR, "Amit");
managers.put(Department.IT, "Rahul");
managers.put(Department.SALES, "Priya");Retrieve a value:
System.out.println( managers.get(Department.IT));Output:
RahulWhen the key type is an enum, EnumMap clearly expresses that relationship.
Enum and switch Best Practices
For a small number of enum states, a switch can be very readable:
switch (status) {
case PENDING: // ...
break;
case APPROVED: // ...
break;
case REJECTED: // ...
break;
}For behavior that naturally belongs to each enum constant, however, an enum method can sometimes produce a cleaner design:
enum Status {
PENDING {
public String message() {
return "Waiting";
}
}, APPROVED {
public String message() {
return "Approved";
}
}, REJECTED {
public String message() {
return "Rejected";
}
};
public abstract String message();
}Choose the approach based on where the behavior logically belongs.
Enum and Serialization
Enums have special serialization behavior in Java.
An enum constant is serialized by its name rather than by serializing an ordinary object field-by-field in the same way as a typical Serializable class.
This is one reason enum constants are useful for stable symbolic values.
You generally do not implement Serializable yourself for an enum.
Enum Cannot Extend Another Class
An enum cannot extend an arbitrary class.
For example, this is not allowed:
enum Status extends SomeClass {
}An enum already derives from:
java.lang.EnumHowever, an enum can implement interfaces:
interface Describable {
String describe();
}enum Status implements Describable {
ACTIVE, INACTIVE;
public String describe() {
return name();
}
}This gives enums a way to share behavior contracts without extending another class.
Enum Is a Class-Like Type
An enum may look simple:
enum Color {
RED, GREEN, BLUE
}But enum types can contain:
Fields
Constructors
Methods
Interfaces
Abstract methods
Constant-specific implementations
Annotations
This makes enums much more powerful than a simple list of strings.
Built-In Methods From java.lang.Enum
Every enum implicitly extends java.lang.Enum.
Useful methods include:
name()ordinal()toString()compareTo()equals()hashCode()getDeclaringClass()For example:
Status status = Status.ACTIVE;
System.out.println(status.name());
System.out.println(status.ordinal());
System.out.println(status.getDeclaringClass());The exact method behavior should be understood before using enum values as business identifiers.
compareTo() With Enums
Enum constants can be compared using their natural declaration order.
Example:
enum Priority {
LOW, MEDIUM, HIGH
}Then:
System.out.println( Priority.LOW.compareTo(Priority.HIGH));The result is negative because LOW appears before HIGH.
However, declaration order is not automatically the same thing as business priority.
If business ordering is important, an explicit field or comparator can make that intention clearer.
Common Enum Mistakes
Mistake 1: Using Strings for Fixed Values
Instead of:
String status = "approved";consider:
Status status = Status.APPROVED;when the set of possible values is fixed.
Mistake 2: Using ordinal() as a Business ID
Avoid relying on:
Status.APPROVED.ordinal()for database identifiers or external APIs.
Use an explicit field instead.
Mistake 3: Assuming valueOf() Is Case-Insensitive
This:
Status.valueOf("approved");does not automatically match:
Status.APPROVEDIf input comes from users or external systems, normalize and validate it explicitly.
Mistake 4: Forgetting Unknown External Values
External systems may introduce values that your current enum does not contain.
For example:
Status.valueOf(input);can throw IllegalArgumentException.
Handle external input appropriately.
Mistake 5: Putting Too Much Logic Into an Enum
Enums can contain methods and complex behavior, but that does not mean every piece of business logic belongs inside the enum.
Keep the design focused and readable.
Enum vs Constants
Before enums, developers often used constants:
public static final int LOW = 1;
public static final int MEDIUM = 2;
public static final int HIGH = 3;This works, but the values are just integers.
A method could accidentally receive:
999With an enum:
enum Priority {
LOW, MEDIUM, HIGH
}the method can require:
void process(Priority priority)The compiler then helps enforce the intended type.
Enum vs String Constants
Another common approach is:
public static final String ACTIVE = "active";
public static final String INACTIVE = "inactive";This is still weaker than:
enum Status {
ACTIVE, INACTIVE
}because strings can contain arbitrary values and do not communicate the complete allowed set through the type system.
Enums are usually clearer when the values form a closed set.
Practical Example: Order Processing
Consider an online store:
enum OrderStatus {
CREATED, CONFIRMED, PACKED, SHIPPED, DELIVERED, CANCELLED
}A method can then accept:
public void updateStatus(OrderStatus status) {
// update order
}Usage:
updateStatus(OrderStatus.SHIPPED);This makes the order state model explicit.
You can also add behavior:
enum OrderStatus {
CREATED("Order created"), CONFIRMED("Order confirmed"), PACKED("Order packed"), SHIPPED("Order shipped"), DELIVERED("Order delivered"), CANCELLED("Order cancelled");
private final String message;
OrderStatus(String message) {
this.message = message;
} public String getMessage() {
return message;
}
}Now each state contains its own display message.
Practical Example: User Roles
enum Role {
ADMIN, MANAGER, EDITOR, USER
}Use it in a class:
class User {
private String name;
private Role role;
public User(String name, Role role) {
this.name = name;
this.role = role;
} public boolean canEdit() {
return role == Role.ADMIN || role == Role.MANAGER || role == Role.EDITOR;
}
}The enum makes the allowed role values explicit.
Practical Example: Priority With a Numeric Level
enum Priority {
LOW(1), MEDIUM(2), HIGH(3), CRITICAL(4);
private final int level;
Priority(int level) {
this.level = level;
} public int getLevel() {
return level;
}
}Usage:
Priority priority = Priority.CRITICAL;
if (priority.getLevel() >= 3) {
System.out.println("Handle urgently");
}Here, the explicit level field represents business meaning instead of relying on ordinal().
Java Enum Cheat Sheet
enum↓Defines a fixed set of constantsvalues()↓Returns all enum constantsvalueOf()↓Converts an exact matching name to an enum constantname()↓Returns the declared constant nameordinal()↓Returns declaration positionEnumSet↓Efficient set for enum valuesEnumMap↓Map optimized for enum keysBasic enum
enum Status {
ACTIVE, INACTIVE
}Enum with field
enum Status {
ACTIVE(1), INACTIVE(0);
private final int code;
Status(int code) {
this.code = code;
} public int getCode() {
return code;
}
}Enum with interface
interface Describable {
String describe();
}enum Status implements Describable {
ACTIVE, INACTIVE;
@Override public String describe() {
return name();
}
}Frequently Asked Questions
What is an enum in Java?
An enum is a special Java type used to represent a fixed set of named constants.
Are enum constants objects?
Yes. Each enum constant is an instance of its enum type.
Can an enum have constructors?
Yes. Enum constructors can initialize fields associated with each constant, but callers cannot instantiate enum objects with new.
Can an enum have methods?
Yes. An enum can contain instance methods, static methods, abstract methods, and constant-specific implementations.
Can an enum implement an interface?
Yes. An enum can implement one or more interfaces.
Can an enum extend a class?
An enum cannot extend an arbitrary class because enum types already extend java.lang.Enum.
What does values() do?
It returns an array containing the enum constants in their declaration order.
What does valueOf() do?
It returns the enum constant whose name exactly matches the supplied string, or throws IllegalArgumentException if there is no match.
What is ordinal()?
ordinal() returns the zero-based declaration position of an enum constant.
Should ordinal() be used as a database ID?
Generally, no. Enum declaration order can change. Use an explicit stable code when a persistent identifier is required.
What is EnumSet?
EnumSet is a specialized Set implementation designed specifically for enum elements.
What is EnumMap?
EnumMap is a specialized Map implementation designed for enum keys.
Suggested Graphics and Page Design
Graphic 1 — Basic Enum Structure
Java Enum
│
┌─────────┼─────────┐
▼ ▼ ▼
Constant Constant Constant
LOW MEDIUM HIGHGraphic 2 — Enum With Data
Priority Enum
│
┌────┼─────────────┐
▼ ▼ ▼
LOW MEDIUM HIGH
1 2 3Graphic 3 — Enum With Interface
Interface
Describable
│
▼
Java Enum
│
┌───────┼───────┐
▼ ▼ ▼
ACTIVE PENDING CLOSEDGraphic 4 — Enum Collections
Enum Values
│
┌───┴────┐
▼ ▼
EnumSet EnumMap
│ │
Set Key → ValueUse clean technical diagrams with Java code snippets, simple boxes, and arrows. Avoid generic stock photos because diagrams communicate the enum concepts more effectively.
Runnable Code Example: Java Enums
Java 17+public class EnumDemo {
public enum OrderStatus {
PENDING(1, "Awaiting Payment"), PROCESSING(2, "Preparing for Dispatch"), SHIPPED(3, "In Transit"), DELIVERED(4, "Delivered to Customer");
private final int code;
private final String description;
OrderStatus(int code, String description) {
this.code = code;
this.description = description;
} public String getDescription() {
return description;
}
} public static void main(String[] args) {
OrderStatus status = OrderStatus.SHIPPED;
System.out.println("Status: " + status.name() + " -> " + status.getDescription());
}
}