Enum Methods and Enums in Switch

Naveen AnamaneniUpdated · 5 min read

Every enum gets a set of methods for free: some the compiler writes for you (values() and valueOf()), and some inherited from java.lang.Enum (name(), ordinal(), compareTo()). They let you loop over all constants, turn user input into a constant, and sort constants in declaration order. Enums also fit switch perfectly, including exhaustive switch expressions that need no default.

The Built-In Methods

Orders.java▶ Try it
import java.util.Arrays;
 
public class Orders {
    enum Status { PLACED, PACKED, SHIPPED, DELIVERED }
 
    public static void main(String[] args) {
        System.out.println(Arrays.toString(Status.values()));
 
        Status s = Status.valueOf("SHIPPED");
        System.out.println(s.name() + " is step " + (s.ordinal() + 1));
        System.out.println(s.compareTo(Status.DELIVERED));
 
        try {
            Status.valueOf("shipped");
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }
 
        Status fromUser = Status.valueOf(" packed ".strip().toUpperCase());
        System.out.println("Parsed: " + fromUser);
    }
}
Output
[PLACED, PACKED, SHIPPED, DELIVERED]
SHIPPED is step 3
-1
No enum constant Orders.Status.shipped
Parsed: PACKED

How it works

  1. values() returns a new array of all constants in declaration order.
  2. valueOf("SHIPPED") finds the constant with that exact name.
  3. name() returns the constant's name; ordinal() its position, counting from 0.
  4. compareTo compares by declaration order: SHIPPED comes before DELIVERED, so the result is negative.
  5. valueOf is case-sensitive and throws IllegalArgumentException for unknown names. Normalize user input with strip() and toUpperCase() first.

Method Reference

MethodComes fromNotes
static E[] values()Generated by the compilerA new array on each call
static E valueOf(String name)Generated by the compilerExact, case-sensitive match
String name()java.lang.Enumfinal; always the declared name
String toString()java.lang.EnumReturns name() by default; can be overridden for display
int ordinal()java.lang.EnumPosition from 0; changes if constants are reordered
int compareTo(E other)java.lang.EnumOrder of declaration
Class<E> getDeclaringClass()java.lang.EnumThe enum type

Enums in switch

Tracking.java▶ Try it
public class Tracking {
    enum Status { PLACED, PACKED, SHIPPED, DELIVERED }
 
    static String message(Status s) {
        return switch (s) {
            case PLACED -> "We have your order";
            case PACKED -> "Packed and ready";
            case SHIPPED -> "On the way";
            case DELIVERED -> "Delivered. Enjoy!";
        };
    }
 
    public static void main(String[] args) {
        for (Status s : Status.values()) {
            System.out.println(s + ": " + message(s));
        }
    }
}
Output
PLACED: We have your order
PACKED: Packed and ready
SHIPPED: On the way
DELIVERED: Delivered. Enjoy!

Inside the case labels you write PLACED, not Status.PLACED. Because the switch expression lists every constant, it's exhaustive and needs no default. If someone adds RETURNED later, this switch stops compiling until it's handled, which is exactly what you want.

Common Mistakes

valueOf on raw user input. Normalize the case and spaces, and catch IllegalArgumentException.

Writing case Status.PLACED. Older Java required the bare constant name; it's always clearest.

Relying on toString() for parsing. If toString() is overridden for display, valueOf still needs name().

Under the Hood

javap -p shows what the compiler turns an enum into:

javap -p Orders$Status
final class Orders$Status extends java.lang.Enum<Orders$Status> {
  public static final Orders$Status PLACED;
  public static final Orders$Status PACKED;
  public static final Orders$Status SHIPPED;
  public static final Orders$Status DELIVERED;
  private static final Orders$Status[] $VALUES;
  public static Orders$Status[] values();
  public static Orders$Status valueOf(java.lang.String);
  private Orders$Status();
  private static Orders$Status[] $values();
  static {};
}

An enum is a final class extending Enum, each constant is a public static final field created in the static block, the constructor is private, and values() returns a copy of the hidden $VALUES array. That's also why new Status() fails with enum classes may not be instantiated.

Interview Corner

What is the difference between name() and toString() for an enum?

name() is final and always returns the constant's exact declared name. toString() returns the same by default but can be overridden, for example to return a display label. Use name() when the exact identifier matters, such as for valueOf or storage.

What does valueOf() do with an invalid name?

It throws IllegalArgumentException with a message like "No enum constant Orders.Status.shipped". The match is exact and case-sensitive; passing null throws NullPointerException.

Practice

  1. Easy: For an enum Planet with five constants, print each constant's name and ordinal using values().
  2. Harder: Write static Status parse(String text) that accepts any case and surrounding spaces, and returns PLACED for unknown text instead of throwing.

Quick check: Enum methods

4 questions
1What does ordinal() return for the first constant?
2Status.valueOf("shipped") when the constant is SHIPPED:
3Which should you store in a database?
4Why does a switch expression over all enum constants need no default?

Key Takeaways

Was this tutorial helpful?

Lesson 166 of 482