Question

Java Enum Comparison: Should You Use == or equals()?

javaenums

Question

In Java, enum values are compiled into class instances with private constructors and a fixed set of public static constants. When comparing two values from the same enum, I have usually written code like this:

public void useEnums(SomeEnum a) {
    if (a.equals(SomeEnum.SOME_ENUM_VALUE)) {
        // ...
    }
}

However, I also found code that compares enum values using == instead:

public void useEnums2(SomeEnum a) {
    if (a == SomeEnum.SOME_ENUM_VALUE) {
        // ...
    }
}

Which form should be used when comparing Java enum constants: == or .equals()?

Short Answer

By the end of this page, you will understand why Java enums are usually compared with ==, when .equals() also works, and why == is generally the safer and clearer choice. You will also see how enum comparison behaves with null, how it is used in real codebases, and what mistakes beginners commonly make.

Concept

In Java, an enum defines a fixed set of named constants. Each enum constant is a single shared instance of that enum type.

For example:

enum Status {
    PENDING,
    APPROVED,
    REJECTED
}

Here, Status.PENDING is not just a value like a number or a string. It is a unique object instance created by the Java runtime. There is exactly one instance for each enum constant.

That is why == works so well with enums:

  • == checks whether two references point to the exact same object
  • enum constants are guaranteed to be unique singletons
  • so identity comparison is the correct comparison

.equals() also returns the same result for enum constants, because enum equality is based on identity too. However, == is preferred because:

  • it is simpler and clearer
  • it directly expresses identity comparison
  • it avoids NullPointerException in cases like a.equals(...) when a is null

This matters in real programming because enums are often used for:

  • application states
  • configuration modes
  • user roles
  • API response types
  • switch-based business logic

Using the right comparison style makes code safer, more readable, and more idiomatic in Java.

Mental Model

Think of enum constants like official badges issued by a company.

  • There is only one real badge for MANAGER
  • There is only one real badge for EMPLOYEE
  • If two people hold the exact same badge object, you can check that with ==

You do not need to inspect the badge contents with .equals() because the system guarantees there is only one official instance of each badge.

So with enums, == is like asking:

Is this the exact official enum constant?

That is exactly what you usually want.

Take Quiz

Syntax and Examples

Basic syntax

Use == to compare enum constants:

enum Direction {
    NORTH, SOUTH, EAST, WEST
}

public class Main {
    public static void main(String[] args) {
        Direction d = Direction.NORTH;

        if (d == Direction.NORTH) {
            System.out.println("Going north");
        }
    }
}

This works because Direction.NORTH is a single unique instance.

.equals() also works, but is not preferred

if (d.equals(Direction.NORTH)) {
    System.out.println("Going north");
}

This is usually unnecessary. It is also less safe if d might be null.

Null-safe comparison

Direction d = null;

if (d == Direction.NORTH) {
    System.out.println("North");
} else {
    System.out.println("Not north or null");
}

This is safe. The result is simply false.

But this is unsafe:

Direction d = null;

if (d.equals(Direction.NORTH)) {
    System.out.println("North");
}

This throws a NullPointerException.

Example with a method

enum PaymentStatus {
    PENDING,
    PAID,
    FAILED
}

public class PaymentService {
    public void handle(PaymentStatus status) {
        if (status == PaymentStatus.PAID) {
            System.out.println("Ship the order");
        } else if (status == PaymentStatus.FAILED) {
            System.out.println("Notify the customer");
        }
    }
}

This is the normal style you will see in Java code.

Step by Step Execution

Consider this example:

enum Light {
    RED, GREEN, YELLOW
}

public class Demo {
    public static void main(String[] args) {
        Light current = Light.GREEN;

        if (current == Light.GREEN) {
            System.out.println("Go");
        }
    }
}

Step by step:

  1. Light is declared with three enum constants: RED, GREEN, and YELLOW.
  2. Java creates one unique instance for each constant.
  3. Light current = Light.GREEN; stores a reference to the GREEN instance.
  4. if (current == Light.GREEN) compares two references:
    • current
    • the enum constant Light.GREEN
  5. Both references point to the exact same enum instance.
  6. The condition evaluates to true.
  7. System.out.println("Go"); runs.

Now compare with null:

Light current = null;

if (current == Light.GREEN) {
    System.out.println("Go");
} else {
    System.out.println("Stop or unknown");
}

Step by step:

  1. current holds null, not an enum instance.
  2. current == Light.GREEN checks whether null is the same reference as Light.GREEN.
  3. It is not, so the result is false.
  4. The else block runs.

No exception is thrown.

Now the unsafe version:

Light current = null;

if (current.equals(Light.GREEN)) {
    System.out.println("Go");
}

Step by step:

  1. current is null.
  2. Java tries to call .equals() on null.
  3. That is not allowed.
  4. A NullPointerException is thrown before the comparison can finish.

Real World Use Cases

Enums are commonly used wherever a program needs a small fixed set of valid options.

Application state

if (orderStatus == OrderStatus.SHIPPED) {
    sendTrackingEmail();
}

User roles

if (userRole == Role.ADMIN) {
    showAdminPanel();
}

Feature modes and configuration

if (environment == Environment.PRODUCTION) {
    enableCaching();
}

API or workflow status handling

if (responseStatus == ApiStatus.ERROR) {
    logFailure();
}

State machines

if (trafficLight == Light.RED) {
    stopCars();
}

In all of these cases, == is the most natural comparison because you are checking whether a value is one specific enum constant.

Take Quiz

Real Codebase Usage

In real Java projects, developers almost always compare enums with ==.

Common pattern: guard clauses

public void process(Status status) {
    if (status == Status.DISABLED) {
        return;
    }

    // continue processing
}

This is concise and null-safe.

Common pattern: validation and branching

public void handleRole(Role role) {
    if (role == Role.ADMIN) {
        grantAllPermissions();
    } else if (role == Role.EDITOR) {
        grantEditorPermissions();
    }
}

Common pattern: switch with enums

When there are many enum cases, developers often use switch instead of repeated if checks:

switch (status) {
    case PENDING:
        System.out.println("Waiting");
        break;
    case PAID:
        System.out.println("Completed");
        break;
    case FAILED:
        System.out.println("Try again");
        break;
}

Common pattern: null-safe checks before logic

Even in codebases with nullable values, == remains the preferred way to compare an enum to a specific constant:

if (status == Status.PAID) {
    archiveInvoice();
}

That avoids defensive code like:

if (status != null && status.equals(Status.PAID)) {
    archiveInvoice();
}

The == version is shorter and safer.

Common Mistakes

Mistake 1: Calling .equals() on a possibly null enum

Broken code:

Status status = null;

if (status.equals(Status.ACTIVE)) {
    System.out.println("Active");
}

Problem:

  • This throws NullPointerException

Better:

if (status == Status.ACTIVE) {
    System.out.println("Active");
}

Mistake 2: Treating enums like strings

Broken thinking:

  • Strings are often compared with .equals()
  • so beginners assume enums should be compared the same way

But enums are different:

  • strings may have different object instances with the same text
  • enum constants are unique single instances

Correct:

if (level == Level.HIGH) {
    alert();
}

Mistake 3: Comparing enum names as text unnecessarily

Broken code:

if (status.name().equals("PAID")) {
    shipOrder();
}

Problems:

  • more fragile
  • less readable
  • tightly couples logic to string text

Better:

if (status == Status.PAID) {
    shipOrder();
}

Mistake 4: Assuming == is wrong for all objects

For most regular objects, == checks reference identity, not logical equality. That is why developers learn to use .equals() for many classes.

However, enums are a special case where identity comparison is exactly what you want.

Mistake 5: Using ordinal() for logic

Broken code:

if (status.ordinal() == 1) {
    shipOrder();
}

Problem:

  • ordinal() depends on declaration order
  • reordering enum constants can break logic

Better:

if (status == Status.PAID) {
    shipOrder();
}

Comparisons

Comparison styleWorks for enums?Null-safe when variable may be null?Recommended?Notes
a == SomeEnum.VALUEYesYesYesBest choice for enum constants
a.equals(SomeEnum.VALUE)YesNoUsually noThrows if a is null
SomeEnum.VALUE.equals(a)YesYesSometimes acceptableNull-safe, but less idiomatic than ==
a.name().equals("VALUE")SometimesNoNoUses strings unnecessarily

Enum comparison vs string comparison

TypePreferred comparison
enum==
String.equals()

if/else vs switch for enums

ApproachBest when
if/elseYou only need one or two checks
switchYou need to handle many enum values

Key takeaway:

  • For enums, prefer ==
  • For strings and many regular objects, prefer .equals()
Take Quiz

Cheat Sheet

// Preferred enum comparison
if (status == Status.ACTIVE) {
    // ...
}

// Works, but not preferred
if (status.equals(Status.ACTIVE)) {
    // ...
}

Rules

  • Use == to compare enum constants
  • == is safe even if the enum variable is null
  • .equals() works, but can throw NullPointerException
  • Do not compare enums using name() unless you specifically need text
  • Do not use ordinal() for business logic

Null behavior

Status status = null;

status == Status.ACTIVE      // false
status.equals(Status.ACTIVE) // NullPointerException

Best practice

if (role == Role.ADMIN) {
    allowAccess();
}

Remember

  • Enums are unique singleton constants
  • == checks identity
  • For enums, identity is the correct comparison

FAQ

Should I always use == for Java enums?

Yes, in normal enum-to-enum comparisons, == is the standard and recommended approach.

Does .equals() work for enums in Java?

Yes, it works when the enum reference is not null, but it is usually unnecessary.

Why is == safe for enums but not for strings?

Enum constants are unique singleton instances. Strings are regular objects, so two different string objects can contain the same text.

Can == throw a NullPointerException with enums?

No. If the enum variable is null, the comparison simply evaluates to false.

Is SomeEnum.VALUE.equals(a) better than a.equals(SomeEnum.VALUE)?

It is safer because it avoids NullPointerException when a is null, but a == SomeEnum.VALUE is still clearer and more idiomatic.

Should I compare enums using name() or toString()?

Usually no. Compare the enum constants directly with == unless you specifically need text for display or parsing.

What if I need to handle many enum values?

Use a switch statement or switch expression for cleaner branching logic.

Take Quiz

Mini Project

Description

Build a small Java program that processes an order status using an enum. This project demonstrates the correct way to compare enum constants with ==, how to handle null safely, and how enum-based branching appears in practical code.

Goal

Create a program that reads an order status value and prints the correct action for each status using enum comparison.

Requirements

  1. Create an OrderStatus enum with at least PENDING, PAID, SHIPPED, and CANCELLED.
  2. Write a method that accepts an OrderStatus value and prints a message based on the status.
  3. Use == for enum comparisons.
  4. Handle a null status safely.
  5. Include a main method that tests multiple status values.
Take Quiz

Keep learning

Related questions

View more