enum
TypesIn Java, an enum
(short for enumeration) is a special reference type that represents a fixed set of constant values. Unlike traditional constants defined with static final
fields, enums provide a type-safe and expressive way to represent a group of related constants. This makes your code clearer, more maintainable, and less error-prone.
enum
To declare an enum, use the enum
keyword followed by the name of the type and a list of constant values separated by commas:
public enum Day {
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY
}
Here, Day
is an enum type with seven predefined constants representing days of the week.
Though enums look like constants, they are actually full-fledged reference types—similar to classes. This means:
You can declare variables of the enum type and assign one of its constants:
Day today = Day.WEDNESDAY;
if (today == Day.WEDNESDAY) {
System.out.println("It's midweek.");
}
The comparison uses ==
because enum constants are unique instances, guaranteeing safe reference equality checks. This is a significant advantage over using plain constants (like int
or String
), where equality comparisons can be error-prone.
public class EnumExample {
public enum TrafficLight {
RED,
YELLOW,
GREEN
}
public static void main(String[] args) {
TrafficLight signal = TrafficLight.RED;
switch (signal) {
case RED:
System.out.println("Stop!");
break;
case YELLOW:
System.out.println("Get ready.");
break;
case GREEN:
System.out.println("Go!");
break;
}
}
}
This example demonstrates how enums make control flow with related constants straightforward and readable.
Before enums, developers often used public static final
constants or integer #define
-style constants for sets of related values. For example:
public static final int RED = 0;
public static final int YELLOW = 1;
public static final int GREEN = 2;
While functional, this approach suffers from several issues:
0
, 1
, or 2
is not self-evident.Enums solve these problems elegantly:
Declaring enum
types elevates your code from primitive constants to meaningful, type-safe abstractions. This clarity reduces bugs, improves readability, and aligns your design closer to the problem domain. Enums also serve as a foundation for more advanced features such as associating data and behavior with constants, which you'll explore in the next sections.
Using enums is a best practice for representing fixed sets of values in Java — a modern and robust alternative to traditional constant patterns.
In Java, enum constants are the predefined fixed instances declared inside an enum type. Each constant represents a unique, immutable object of that enum class. Understanding how to define, access, and iterate over these constants is fundamental to leveraging enums effectively.
Enum constants are declared as comma-separated identifiers within the enum body, usually written in all uppercase letters to follow Java naming conventions for constants. For example:
public enum Season {
WINTER,
SPRING,
SUMMER,
FALL
}
Here, WINTER
, SPRING
, SUMMER
, and FALL
are the enum constants of type Season
. They are implicitly public static final
instances created by the Java compiler.
You can access enum constants using the dot notation directly through the enum type:
Season currentSeason = Season.SUMMER;
System.out.println("The current season is " + currentSeason);
This assigns the constant SUMMER
to the variable currentSeason
and prints it. Enum constants are singleton instances, so comparison using ==
is safe and recommended:
if (currentSeason == Season.SUMMER) {
System.out.println("Time for the beach!");
}
Java provides a built-in static method called values()
for every enum type, which returns an array of all declared constants in the order they are defined. This is useful for iteration:
for (Season s : Season.values()) {
System.out.println(s);
}
Output:
WINTER
SPRING
SUMMER
FALL
Using values()
enables you to loop through all possible enum constants, which is particularly helpful for displaying options or validating input.
==
.toString()
Implementation: By default, calling toString()
on an enum constant returns its name, e.g., "SUMMER"
.The standard convention for enum constants is to use uppercase letters with words separated by underscores (_
), similar to static final constants. This convention improves readability and instantly signals their constant nature:
public enum TrafficSignal {
RED,
YELLOW,
GREEN
}
Following naming conventions makes your code more consistent and easier to understand by other developers.
public class Main {
// Define the enum
public enum Season {
WINTER,
SPRING,
SUMMER,
FALL
}
public static void main(String[] args) {
// Accessing an enum constant
Season currentSeason = Season.SUMMER;
System.out.println("The current season is " + currentSeason);
// Comparison using ==
if (currentSeason == Season.SUMMER) {
System.out.println("Time for the beach!");
}
// Iterating over enum constants
System.out.println("All seasons:");
for (Season s : Season.values()) {
System.out.println(s);
}
}
}
Enum constants provide a clean, type-safe, and immutable way to represent fixed sets of values. Their well-defined lifecycle—created once and never modified—makes them reliable throughout your application. The ability to iterate over all constants using values()
simplifies many common programming tasks, like menus or state handling.
Moreover, the naming conventions for enums contribute to clear communication of their purpose in code, aligning with Java's broader emphasis on readability and maintainability.
By using enum constants properly, you ensure your code is both robust and expressive, avoiding the pitfalls of traditional integer or string constants.
Java enums are more than just simple collections of constants—they can have fields, constructors, and methods, allowing you to attach data and behavior directly to each enum constant. This makes enums powerful alternatives to small classes when you need to group related values with associated logic.
You can define fields inside an enum and set them via a private constructor. For example, consider a Day
enum that stores a display name for each day:
public enum Day {
MONDAY("Mon"),
TUESDAY("Tue"),
WEDNESDAY("Wed"),
THURSDAY("Thu"),
FRIDAY("Fri"),
SATURDAY("Sat"),
SUNDAY("Sun");
private final String displayName;
// Private constructor to set the displayName
Day(String displayName) {
this.displayName = displayName;
}
// Getter method for displayName
public String getDisplayName() {
return displayName;
}
}
Each enum constant calls the constructor with a specific displayName
. The constructor is implicitly private to prevent external instantiation.
Enums can have methods that operate on their fields or implement logic unique to the enum type. For instance:
public class Main {
public static void main(String[] args) {
Day today = Day.MONDAY;
System.out.println("Today is " + today.getDisplayName()); // Output: Today is Mon
}
}
This shows how you can retrieve a friendly name for each day through getDisplayName()
. You can add more methods to your enum to encapsulate behavior related to its constants.
public class Main {
public enum Day {
MONDAY("Mon"),
TUESDAY("Tue"),
WEDNESDAY("Wed"),
THURSDAY("Thu"),
FRIDAY("Fri"),
SATURDAY("Sat"),
SUNDAY("Sun");
private final String displayName;
Day(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return displayName;
}
}
public static void main(String[] args) {
Day today = Day.MONDAY;
System.out.println("Today is " + today.getDisplayName());
System.out.println("All days:");
for (Day day : Day.values()) {
System.out.println(day.name() + " -> " + day.getDisplayName());
}
}
}
By combining data and behavior, enums become self-contained, strongly typed objects, often eliminating the need for separate classes to represent fixed sets of related values. This:
Overall, enums with fields and methods offer a concise yet expressive way to represent complex concepts that naturally fit into a fixed set of named instances.
switch
StatementsEnums integrate seamlessly with Java's switch
statement, providing a clear, type-safe way to branch logic based on a fixed set of predefined constants. Using enums in a switch
block is both expressive and less error-prone compared to using primitive types like int
or String
.
Here's a straightforward example that prints messages based on the day of the week using an enum:
public enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
public class Main {
public static void printMessage(Day day) {
switch (day) {
case MONDAY:
System.out.println("Start of the workweek!");
break;
case FRIDAY:
System.out.println("Almost weekend!");
break;
case SATURDAY:
case SUNDAY:
System.out.println("It's the weekend!");
break;
default:
System.out.println("Midweek days are productive.");
break;
}
}
public static void main(String[] args) {
printMessage(Day.MONDAY); // Output: Start of the workweek!
printMessage(Day.WEDNESDAY); // Output: Midweek days are productive.
printMessage(Day.SUNDAY); // Output: It's the weekend!
}
}
When you use an enum in a switch
statement, the compiler ensures:
case
labels. If you try to switch on a value not part of the enum, the code won't compile.switch
variable must be of the enum type or compatible with it, preventing accidental mixing of unrelated types.switch
, reducing the chance of missing cases.This level of type safety prevents common bugs caused by mistyping string literals or incorrect integer constants.
Using enums in switch
statements makes your code:
MONDAY
and SUNDAY
are clearer than arbitrary numbers or strings.switch
statements accordingly.SATURDAY
and SUNDAY
both print "It's the weekend!"), improving conciseness.switch
and Enumsenum
values directly in case
labels without prefixing them with the enum type (e.g., case MONDAY:
instead of case Day.MONDAY:
).default
case handles any unmatched enum values, although it may be unnecessary if you cover all constants explicitly.switch
expression can return values directly, further improving clarity when working with enums.Switching on enums leverages Java's type system to create expressive and safe branching logic. Compared to switching on strings or integers, enums reduce the risk of runtime errors caused by invalid values, making your code robust and easier to understand. They serve as a natural fit for controlling program flow where a variable can only have a limited set of valid states.