Table of Contents

Enum in Java: A Complete Beginner’s Guide with Examples

  • Last Updated: July 29, 2026
  • By: javahandson
  • Series
img

Enum in Java: A Complete Beginner’s Guide with Examples

Learn what an enum in Java is, how to declare one, and how to use fields, constructors, methods, switch, EnumSet, and EnumMap — with clear beginner examples.

1. Introduction

You’ve probably had a value that can only be one of a few fixed things. A day of the week. A traffic light color. An order status like PENDING or SHIPPED. You could store these as plain strings or numbers, but that gets messy fast.

That’s the exact problem an enum in Java solves. An enum lets you define a small, fixed set of named values. Once you have it, the compiler stops you from using anything outside that set.

Think of a traffic light. It shows RED, YELLOW, or GREEN. It never shows PURPLE. An enum captures that idea in code, so your program can only ever use the values you allow.

In this article, we’ll start with what an enum really is. Then we’ll build up from tiny examples to the powerful stuff, like enums with fields, methods, and constructors.

We’ll keep every example short and runnable. You can copy each one into your editor and try it right away. That’s the best way to make enums stick.

Here’s what we’ll cover:

  • What an enum is, and why strings and constants fall short
  • How to declare and use a basic enum
  • Built-in helpers like values(), valueOf(), ordinal(), and name()
  • Enums with fields, constructors, and methods
  • Using enums inside switch statements
  • EnumSet and EnumMap, and why they beat regular collections here
  • Common mistakes and the interview questions that keep coming up

No deep background needed. If you can write a simple Java class, you’re ready to go.

enum in java

2. What Is an Enum?

An enum is a special type that holds a fixed group of constants. The word enum is short for enumeration, which just means a listing of items.

Each value in an enum is called a constant. You write them in capital letters by convention. And each one is a real object, not just a label.

You define an enum once, up front. After that, those are the only values allowed. Nothing else can ever be that type.

2.1 Why Not Just Use Strings?

Before enums, people stored fixed choices as strings. A status field might hold “ACTIVE” or “INACTIVE”. It works, but it’s risky.

Say you type “Actve” by mistake. The code still compiles. The bug only shows up later, at runtime, when something breaks.

Strings give you no safety net here. Any text is a valid string, even nonsense. So the compiler can’t warn you about a wrong value.

With an enum, a typo won’t compile. You can only use the constants you defined. The compiler catches the error right away, which saves you real debugging time.

2.2 Why Not Just Use int Constants?

Another old trick was using plain int values. You might write a set of static final ints like this:

public static final int RED = 0;
public static final int YELLOW = 1;
public static final int GREEN = 2;

This has problems too. Nothing stops you from passing 7 where a color is expected. The number 7 isn’t a color, but the compiler won’t complain.

Also, when you print the value, you just see a number. You lose the friendly name. An enum keeps the name and blocks bad values, so you get the best of both.

2.3 Enums Are Type-Safe

Here’s the big win. An enum gives you type safety. A method that takes a Color can only accept Color values, never a random int or string.

So your code says what it means. And the compiler enforces it. Bad values simply can’t sneak in through the front door.

Let’s make that concrete. Imagine a method that sets a traffic light. With an enum, the signature reads setLight(Color c). Anyone reading it knows exactly what to pass.

Compare that to setLight(int c). Now the reader has to guess. Is 0 red or green? Is 5 even valid? The enum removes all that doubt.

2.4 Each Constant Is a Real Object

This part surprises a lot of beginners. Each enum constant is a full-blown object. It’s created once, and Java keeps just one copy of it.

Because there’s only one copy, you can safely compare with ==. Two references to Day.MONDAY point at the very same object in memory.

This single-instance behavior also makes enums a clean way to write a singleton. We’ll touch on that later when we cover constructors.

2.5 Enum vs String vs int: A Quick Comparison

It helps to see the three approaches side by side. All three can model a fixed choice. But they don’t offer the same safety.

Feature String int constant Enum
Type-safe No No Yes
Typo caught at compile time No No Yes
Readable output Yes No Yes
Can hold extra data No No Yes
Works in switch Yes Yes Yes
Fixed set enforced No No Yes

The enum column wins almost every row. That’s why modern Java code leans on enums for any small, fixed set of options.

2.6 When Should You Use an Enum?

A good rule of thumb helps here. Use an enum whenever a value can only be one of a few known choices.

Some everyday examples fit this perfectly:

  • Days of the week, or months of the year.
  • Order states like CREATED, PAID, and SHIPPED.
  • Directions such as NORTH, SOUTH, EAST, WEST.
  • User roles like ADMIN, EDITOR, and VIEWER.

If the list is small and known ahead of time, an enum fits. If the values change at runtime or come from users, a plain collection is better.

3. Declaring and Using a Basic Enum

Let’s write our first enum. It’s just the enum keyword, a name, and a list of constants.

3.1 A Simple Enum

Here’s a Day enum with three values. Notice the constants are in capitals, separated by commas.

public enum Day {
    MONDAY,
    TUESDAY,
    WEDNESDAY
}

That’s the whole thing. No fields, no methods, just three named constants. You can already use it in your code.

3.2 Using the Enum

You use an enum value by name, through the type. It reads cleanly and stays type-safe.

Day today = Day.MONDAY;
System.out.println(today);   // Output: MONDAY
 
if (today == Day.MONDAY) {
    System.out.println("Start of the work week");
}

See how we compare with ==? For enums, that’s safe and preferred. Each constant is a single shared object, so == checks identity correctly.

You don’t need equals() here, though it also works. Most Java developers use == with enums because it reads well and never throws a NullPointerException on the left side.

3.3 Where Enums Can Live

You can define an enum in its own file, just like a class. You can also nest it inside a class when it’s only used there.

  • As a top-level type in its own .java file, when many classes use it.
  • Nested inside a class, when only that class needs it.
  • You cannot declare an enum inside a method, though.

Pick the spot that keeps your code tidy. For shared values like order status, a top-level enum usually makes the most sense.

3.4 Naming Your Constants

There’s a simple convention for enum constants. Write them in all capitals, with underscores between words.

So you’d write IN_PROGRESS, not inProgress or InProgress. This matches how Java names other constants, and it makes them easy to spot.

The enum type name itself follows normal class rules. Use PascalCase, like OrderStatus or TrafficLight. Small habits like this keep your code readable.

4. Built-in Enum Methods

Every enum you write comes with handy methods for free. Java adds them behind the scenes. Let’s look at the ones you’ll actually use.

4.1 values() Gives You All Constants

The values() method returns an array of every constant, in the order you declared them. It’s perfect for looping.

for (Day d : Day.values()) {
    System.out.println(d);
}
// Output:
// MONDAY
// TUESDAY
// WEDNESDAY

This is great for building menus, filling dropdowns, or iterating over every option. No manual list needed.

4.2 valueOf() Turns a String Into a Constant

Sometimes you have a string, maybe from user input or a database, and you want the matching enum. Use valueOf() for that.

Day d = Day.valueOf("TUESDAY");
System.out.println(d);   // Output: TUESDAY

One catch. The string must match a constant name exactly, including case. If it doesn’t, valueOf() throws an IllegalArgumentException. So guard your input first.

4.3 ordinal() Gives the Position

The ordinal() method returns the position of a constant, starting at 0. The first constant is 0, the second is 1, and so on.

System.out.println(Day.MONDAY.ordinal());     // 0
System.out.println(Day.WEDNESDAY.ordinal());  // 2

Be careful with ordinal() though. Don’t save it in a database or file. If you reorder your constants later, every stored number now points at the wrong value.

4.4 name() Gives the Exact Name

The name() method returns the constant’s name as a string, exactly as declared. It’s similar to toString(), but you should not override it.

System.out.println(Day.MONDAY.name());   // MONDAY

Use name() when you want the guaranteed, unchanged constant name. Use toString() when you want a display value you might customize.

4.5 A Small Real-World Use

Let’s see these methods work together. Say you get a status string from a web form. You want to turn it into an enum, safely.

String input = "TUESDAY";
 
try {
    Day day = Day.valueOf(input);
    System.out.println("Got: " + day.name());
} catch (IllegalArgumentException e) {
    System.out.println("Not a valid day: " + input);
}

This guards against bad input. A good value becomes an enum. A bad value gets caught, and your program keeps running instead of crashing.

That little try-catch is a habit worth keeping. Any time a string comes from outside your code, wrap valueOf() so a typo can’t take you down.

4.6 A Quick Method Cheat Sheet

Here they are side by side, so you can pick the right one quickly.

Method Returns Common Use
values() Array of all constants Loop over every option
valueOf(String) Matching constant Convert text to enum
ordinal() Position as int Rarely, for internal order
name() Constant name as String Get the exact declared name

5. Enums With Fields, Constructors, and Methods

Here’s where enums get powerful. A Java enum is a full class under the hood. So it can hold data and behavior, not just names.

5.1 Adding a Field and Constructor

Say each planet should carry its own mass. You can attach a value to each constant with a field and a constructor.

public enum Coin {
    PENNY(1),
    NICKEL(5),
    DIME(10),
    QUARTER(25);
 
    private final int cents;
 
    Coin(int cents) {
        this.cents = cents;
    }
 
    public int getCents() {
        return cents;
    }
}

Each constant now passes a value into the constructor. PENNY gets 1, NICKEL gets 5, and so on. The value rides along with the constant.

5.2 A Few Rules to Remember

Enum constructors follow a couple of rules that trip up newcomers. Keep these in mind:

  • The constants must come first, before any fields or methods.
  • End the constant list with a semicolon when you add more members.
  • The constructor is always private, so you can’t make new instances yourself.
  • You can’t call the constructor with new. Java creates the constants once.

That private constructor is the whole point. Java builds each constant a single time, and no one else can create more. That’s why enums make great singletons.

5.3 Using the Field

Now you can ask any constant for its data. Just call the getter you wrote.

Coin c = Coin.QUARTER;
System.out.println(c.getCents());   // 25
 
int total = 0;
for (Coin coin : Coin.values()) {
    total += coin.getCents();
}
System.out.println(total);          // 41

So each coin knows its own worth. This beats a scattered map of values, because the data lives right next to the constant it describes.

5.4 Adding Behavior With Methods

Enums can hold methods too. You can even give each constant its own version of a method. This is called a constant-specific method body.

public enum Operation {
    PLUS {
        public int apply(int a, int b) { return a + b; }
    },
    MINUS {
        public int apply(int a, int b) { return a - b; }
    };
 
    public abstract int apply(int a, int b);
}

Here each operation carries its own logic. PLUS adds, MINUS subtracts. You call apply() and the right code runs for that constant.

System.out.println(Operation.PLUS.apply(3, 4));    // 7
System.out.println(Operation.MINUS.apply(10, 4));  // 6

This pattern replaces long if-else chains. Each constant owns its behavior, so the code stays clean and easy to extend.

💡 Interview Insight
Q: Can a Java enum have a constructor?
A: Yes, but it must be private (or package-private). You can’t call it with new. Java runs the constructor once for each constant when the enum type loads.

5.5 Enums Can Implement Interfaces

An enum can’t extend a class, but it can implement an interface. This lets your constants fit into code that expects a certain contract.

interface Describable {
    String describe();
}
 
public enum Size implements Describable {
    SMALL, MEDIUM, LARGE;
 
    public String describe() {
        return "Size: " + name();
    }
}

Now any Size value can be treated as a Describable. So your enum plugs neatly into general-purpose methods, without giving up its fixed set of values.

5.6 Looking Up a Constant by Its Value

Sometimes you have a stored value and want the matching constant back. A small static helper handles this cleanly.

Say each coin has a cents value, and you want the coin for 25. You can loop over values() and return the match.

public static Coin fromCents(int cents) {
    for (Coin c : Coin.values()) {
        if (c.getCents() == cents) {
            return c;
        }
    }
    throw new IllegalArgumentException("No coin for " + cents);
}

Now Coin.fromCents(25) gives you QUARTER. This pattern is common when you map a database column back to an enum.

For large enums, you’d cache the lookups in a static map instead. But for a handful of constants, this simple loop is perfectly fine.

6. Enums as Singletons

Here’s a neat trick many developers love. An enum is one of the cleanest ways to write a singleton in Java.

A singleton is a class with exactly one instance. You want just one shared object, and no way to make more. Enums give you that for free.

6.1 Why an Enum Works So Well

Recall that Java creates each enum constant once. It also blocks you from calling the constructor yourself. Those two facts are exactly what a singleton needs.

So a single-constant enum is a ready-made singleton. No extra locking, no double-check logic, no clever code. Java handles it all.

public enum Config {
    INSTANCE;
 
    private String appName = "MyApp";
 
    public String getAppName() {
        return appName;
    }
}

There’s just one constant, INSTANCE. That’s your single object. You reach it with Config.INSTANCE, and there’s no way to make a second one.

6.2 Using the Singleton

You call methods on the single instance directly. It reads clean and stays safe across threads.

String name = Config.INSTANCE.getAppName();
System.out.println(name);   // MyApp

This approach is also safe when many threads run at once. Java guarantees the constant is built once, correctly, before anyone uses it.

It even survives serialization cleanly, which trips up hand-written singletons. For these reasons, many experts call the enum singleton the best one.

💡 Interview Insight
Q: Why is an enum considered the best way to write a singleton?
A: Java creates the single constant once, blocks extra instances, and handles thread safety and serialization for you. A hand-written singleton needs careful locking and readResolve logic to match that.

7. Enums in Switch Statements

Enums and switch statements are a natural fit. The switch reads clean, and the compiler helps you catch missing cases.

7.1 The Basic Switch

Inside a switch on an enum, you write just the constant name in each case. You don’t repeat the enum type.

Day today = Day.MONDAY;
 
switch (today) {
    case MONDAY:
        System.out.println("Back to work");
        break;
    case TUESDAY:
        System.out.println("Second day");
        break;
    default:
        System.out.println("Some other day");
}

Notice we write case MONDAY, not case Day.MONDAY. Java already knows the type from the switch. Adding the prefix is actually a compile error.

7.2 Why This Is Safer

A switch on an enum makes your intent clear. And many tools warn you when you forget a case. That warning is a small gift that prevents bugs.

For that reason, enums pair really well with switch logic. State machines, menu handlers, and status flows all benefit from this combo.

7.3 The Newer Switch Style

Modern Java also offers a cleaner switch that returns a value. It uses arrows and skips the break statements. Many teams prefer it now.

String message = switch (today) {
    case MONDAY -> "Back to work";
    case TUESDAY -> "Second day";
    default -> "Some other day";
};
System.out.println(message);

No break needed, and each arm returns a value. So the whole block reads as one clear expression. It’s a nice fit for enums.

💡 Interview Insight
Q: Do you write case Day.MONDAY or case MONDAY inside a switch?
A: Just case MONDAY. The switch already knows the enum type, so writing the qualified name causes a compile error.

8. EnumSet and EnumMap

Java gives you two special collections built just for enums. They’re called EnumSet and EnumMap. Both are fast and memory-light.

8.1 EnumSet for Groups of Constants

An EnumSet holds a group of enum constants. Under the hood, it uses bits, so it’s very compact and quick.

EnumSet<Day> workStart = EnumSet.of(Day.MONDAY, Day.TUESDAY);
 
if (workStart.contains(Day.MONDAY)) {
    System.out.println("Monday is in the set");
}

Use EnumSet instead of HashSet when your keys are enum constants. It’s faster and uses less memory, with no real downside.

8.2 EnumMap for Enum Keys

An EnumMap maps each enum constant to a value. It’s like a HashMap, but tuned for enum keys.

EnumMap<Day, String> plans = new EnumMap<>(Day.class);
plans.put(Day.MONDAY, "Team meeting");
plans.put(Day.TUESDAY, "Code review");
 
System.out.println(plans.get(Day.MONDAY));  // Team meeting

Because it knows the enum ahead of time, EnumMap stores values in a plain array. That makes lookups quick and the memory footprint small.

8.3 A Handy EnumSet Trick

EnumSet comes with a few nice factory methods. You can grab all constants, none of them, or a range, in one line.

EnumSet<Day> all = EnumSet.allOf(Day.class);
EnumSet<Day> none = EnumSet.noneOf(Day.class);
EnumSet<Day> some = EnumSet.range(Day.MONDAY, Day.WEDNESDAY);

These read almost like plain English. So building a set of permissions or flags stays short and easy to follow.

8.4 When to Reach for These

  • Use EnumSet when you need a set of enum values, like a group of permissions.
  • Use EnumMap when you map enum constants to data, like a status to a handler.
  • Skip HashSet and HashMap for enum keys, since these two are simply better here.

9. A Practical Walkthrough

Let’s tie the pieces together with a small, realistic task. Say you’re modeling an order in a shopping app.

9.1 The Order Status Enum

An order moves through a few fixed states. It’s created, then paid, then shipped, then delivered. That’s a perfect fit for an enum.

public enum OrderStatus {
    CREATED("Order placed"),
    PAID("Payment received"),
    SHIPPED("On the way"),
    DELIVERED("Delivered");
 
    private final String label;
 
    OrderStatus(String label) {
        this.label = label;
    }
 
    public String getLabel() {
        return label;
    }
}

Each status carries a friendly label. So you can show “On the way” in the UI while your code still works with the clean SHIPPED constant.

9.2 Reacting to Each Status

Now you handle each state with a switch. The compiler and your tools help you cover every case.

OrderStatus status = OrderStatus.SHIPPED;
 
switch (status) {
    case CREATED:
        System.out.println("Waiting for payment");
        break;
    case PAID:
        System.out.println("Preparing your order");
        break;
    case SHIPPED:
        System.out.println(status.getLabel());
        break;
    case DELIVERED:
        System.out.println("Enjoy!");
        break;
}

Clean and readable, right? Each state maps to one clear action. Adding a new status later is easy, and your tools remind you to handle it.

9.3 Storing the Status Safely

When you save an order, store the name, not the ordinal. That way, reordering constants later never corrupts your old data.

String toSave = status.name();          // "SHIPPED"
OrderStatus loaded = OrderStatus.valueOf(toSave);

This round-trip is safe and clear. You write a stable string, and you read it back into the exact same constant.

9.4 Why This Design Pays Off

Look at what this small enum gave you. The order can only ever be one of four states. No stray string can slip in.

Each state carries its own label for the screen. And the switch makes your logic easy to read at a glance.

Later, if you add a RETURNED state, you edit one enum. Your tools then flag every switch that needs the new case. That’s a lot of safety from a few lines.

10. Enum Best Practices

A few simple habits make your enums cleaner and safer. None of them are hard. They just save you trouble down the road.

10.1 Prefer name() Over ordinal() for Storage

When you save an enum, write its name(), not its ordinal(). Names stay stable even if you reorder or add constants later.

This one habit prevents a whole class of nasty data bugs. So make it your default from day one.

10.2 Keep Enum Logic Inside the Enum

If behavior depends on the constant, put it in the enum itself. A method or a field beats a big switch scattered across your code.

That way, adding a constant means updating one place. Your logic and your data stay together, which is easier to maintain.

10.3 Use EnumSet and EnumMap for Enum Keys

Whenever your keys are enum constants, reach for EnumSet or EnumMap. They’re faster and lighter than the general-purpose versions.

There’s really no downside here. So treat these two as the default choice for enum-keyed collections.

11. Common Mistakes and Pitfalls

A few enum traps catch beginners over and over. Let’s name them so you can steer clear.

11.1 Storing ordinal() in a Database

This one hurts later. If you save ordinal() and then reorder your constants, every stored number now points at the wrong value. Store name() instead, since names stay stable.

11.2 Forgetting valueOf() Is Case-Sensitive

The valueOf() method matches names exactly. Pass “monday” for a MONDAY constant and it throws. Normalize your input, or wrap the call in a try-catch.

11.3 Putting Constants After Members

In an enum with fields, the constants must come first. Put a field before them and the code won’t compile. Always list your constants at the top.

11.4 Trying to Extend an Enum

You can’t make one enum extend another. Every enum already extends java.lang.Enum, and Java allows only one parent. Enums can implement interfaces, though, which covers most needs.

12. Interview Questions on Enums

Q: What is an enum in Java?

A: An enum is a special type that holds a fixed set of named constants. Each constant is a real object, created once. Enums are type-safe, so the compiler blocks any value outside the set you defined.

Q: Can a Java enum have a constructor?

A: Yes. The constructor must be private or package-private, and you cannot call it with new. Java runs it once for each constant when the enum type loads.

Q: What is the difference between name() and ordinal()?

A: name() returns the constant’s exact declared name as a string. ordinal() returns its position, starting at 0. Store name() for persistence, since ordinal values shift if you reorder constants.

Q: Why should I use == instead of equals() with enums?

A: Each enum constant is a single shared object, so == compares identity correctly. It also reads well and never throws a NullPointerException on the left side.

Q: Can an enum extend a class?

A: No. Every enum already extends java.lang.Enum, and Java allows only one parent. An enum can implement interfaces, though, which covers most needs.

Q: When should I use EnumSet and EnumMap?

A: Use EnumSet when you need a group of enum constants, and EnumMap when you map enum keys to values. Both are faster and lighter than HashSet or HashMap for enum keys.

Q: Does valueOf() care about case?

A: Yes. The string must match a constant name exactly, including case. A mismatch throws IllegalArgumentException, so normalize input or wrap the call in a try-catch.

Q: Do you write case MONDAY or case Day.MONDAY in a switch?

A: Just case MONDAY. The switch already knows the enum type, so adding the qualified name causes a compile error.

13. Conclusion

Let’s pull it together. An enum in Java defines a fixed set of named constants. It’s type-safe, readable, and blocks bad values at compile time.

You saw the basics first: declaring constants, comparing with ==, and looping with values(). Then you went further, with fields, constructors, and constant-specific methods.

You also met switch statements, EnumSet, and EnumMap. Each one makes enum-heavy code cleaner and faster.

And you saw two handy patterns: the enum singleton and constant-specific methods. Reach for enums whenever a value has a small, fixed set of options. Your code will be safer and easier to read.

Further Reading

Leave a Comment