A Fixed Set of Named Values
Some values only make sense as one of a small, known list: the days of the week, the suits in a deck, the states an order can be in. You could model these with int codes (0 for pending, 1 for shipped) or strings ("PENDING", "SHIPPED"), but nothing stops a caller from passing 7 or "PNEDING". An enum closes that hole - the type itself only allows the values you declared.
Day is a brand-new type. A variable of type Day can hold exactly one of those seven constants - or null - and nothing else. The compiler rejects Day d = "WEDNESDAY"; or Day d = 2;. That guarantee is the whole point.
Each constant (Day.MONDAY, and so on) is a single shared instance, created once. Because there's only ever one MONDAY, you compare enums with == rather than equals - they're the same object.
Switching on an Enum
Enums pair naturally with switch. You don't even need to qualify each constant with the type name inside the switch:
Inside the switch, write case SATURDAY, not case Day.SATURDAY - Java infers the type. The big win over switching on a string or int is that if you add a new constant later, your IDE and the exhaustiveness checks can flag every switch that forgot to handle it.
Looping Over Every Constant
Every enum automatically gets a static values() method returning all its constants in declaration order, plus an ordinal() giving each constant's zero-based position:
name() gives the constant's identifier as a String, and values() is perfect for building menus or iterating over options. One caution: don't store ordinal() anywhere persistent. If someone reorders the constants later, the numbers shift and your saved data breaks. Treat ordinal() as an implementation detail, not a stable ID.
Enums Are Real Classes: Fields and Methods
This is where Java enums go beyond the named-integer enums of other languages. Each constant can carry data, passed through a constructor, and the enum can have methods. You list the constants first, give each one its constructor arguments, then declare the fields, constructor, and methods after a semicolon.
Note the structure: the constants come first and end with a semicolon, then the rest of the class follows. The constructor is implicitly private - you can never write new Planet(...), because the only instances allowed are the ones declared at the top. The final fields make each constant immutable, which is exactly what you want for shared singletons.
From a String and Back
To turn a string into the matching constant, use the auto-generated valueOf:
valueOf matches the constant name exactly, including case, and throws IllegalArgumentException if there's no match. That's the common gotcha: "shipped" does not match SHIPPED. When parsing user input or external data, normalize the case first (input.toUpperCase()) and wrap the call in a try/catch, or you'll crash on the first bad value.
Per-Constant Behavior
Sometimes each constant needs to behave differently, not just hold different data. You can give an enum an abstract method and have each constant supply its own implementation in a small body:
This is sometimes called the "constant-specific method" pattern. It replaces a sprawling switch over the constant with behavior attached directly to each one - add a new operation and the compiler forces you to define its apply, so you can't forget a case.
When to Reach for an Enum
Use an enum whenever a value is naturally one of a small, fixed, known-at-compile-time set:
- States in a workflow (
PENDING,SHIPPED,DELIVERED). - Categories, modes, or types (
READ,WRITE,EXECUTE). - Any place you were tempted to define a cluster of
public static final intconstants - the enum gives you the same named values plus type safety, a readabletoString, andswitchsupport for free.
Don't use an enum for an open-ended or runtime-determined set (usernames, country list pulled from a database). Enums are baked in at compile time; if the set changes while the program runs, you want a regular collection instead.
Next: Generics
You've now seen values() returning a Planet[] and earlier pages using List<Shape> - that <...> syntax is generics, Java's way of writing one class or method that works for many types while keeping full type safety. Next we'll unpack how List<String> and Map<K, V> actually work and how to write your own generic types.
Frequently Asked Questions
What is an enum in Java?
An enum is a special type whose value can only be one of a fixed, named set of constants - like Day.MONDAY or Status.ACTIVE. Each constant is a single, pre-built instance of the enum. Enums give you type safety: a method that takes a Day can only ever receive a real day, never a typo'd string or an out-of-range int.
Can a Java enum have fields and methods?
Yes. An enum is a full class. You can give each constant constructor arguments, store them in private final fields, and add methods that use them. For example MERCURY(3.3e23, 2.4e6) passes mass and radius to the enum's constructor, and a surfaceGravity() method can compute from those fields.
What is the difference between values() and valueOf() on a Java enum?
values() returns an array of all the enum's constants, in declaration order - handy for looping over every option. valueOf("NAME") does the reverse: it looks up the constant whose name matches the string exactly, and throws IllegalArgumentException if none matches. Both are generated automatically by the compiler.