Java Enum Methods
Table of Contents + โ
In the last lesson you learned about Java enums. But here is what many people miss: each name is a real object that can carry data and behavior, and every enum comes with free methods built in. Letโs open up these enum methods.
๐ค The problem we are solving
Once you have an enum, new questions show up.
- How do I get every value to fill a dropdown menu?
- How do I turn the text
"SHIPPED"from a web form back into the matching value? - How do I attach a price to a coin, or a calculation to a math operation?
The tools are the built-in enum methods plus the fact that an enum is a full class.
๐งฐ The built-in methods every enum has
When you write an enum, Java adds these methods for free. Here is a small enum we will use to try them out.
public enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY}This program calls each built-in method and prints the result.
public class Demo { public static void main(String[] args) {
// values() gives you an array of every constant for (Day d : Day.values()) { System.out.println(d.name() + " is at index " + d.ordinal()); }
// valueOf() turns text into the matching constant Day d = Day.valueOf("FRIDAY"); System.out.println("Got: " + d);
// compareTo() compares by declaration order System.out.println(Day.MONDAY.compareTo(Day.FRIDAY)); }}Output
MONDAY is at index 0TUESDAY is at index 1WEDNESDAY is at index 2THURSDAY is at index 3FRIDAY is at index 4Got: FRIDAY-4Each one in turn.
values()hands back an array of every constant, in declaration order. Great for loops.name()returns the exact text of the constant. SoDay.MONDAY.name()is"MONDAY".ordinal()returns the position, counting from zero.MONDAYis0. Be careful with this one (more later).valueOf(String)is the reverse ofname(). Text in, matching constant out.compareTo()compares two constants by declaration order.MONDAY.compareTo(FRIDAY)is0 - 4, which is-4. A negative result means the first one comes earlier.
๐ค valueOf and name go together
These two are a matched pair. One turns a constant into text, the other turns text back into a constant. Handy when you read a value from a file, a database, or a web form, where everything arrives as a String.
public class Roundtrip { public static void main(String[] args) { Day saved = Day.WEDNESDAY;
String text = saved.name(); // constant -> text System.out.println("Saved as: " + text);
Day back = Day.valueOf(text); // text -> constant System.out.println("Loaded: " + back); System.out.println("Same value? " + (saved == back)); }}Output
Saved as: WEDNESDAYLoaded: WEDNESDAYSame value? trueThe == check returns true because enum constants are single shared objects. There is only ever one WEDNESDAY. One warning: valueOf is strict. The text must match a constant name exactly, including case. The Common Mistakes section covers what happens when it does not.
๐๏ธ An enum is a full class, with fields and a constructor
An enum can have fields, a constructor, and methods, just like a normal class. Each constant is created by calling that constructor with its own values. Think of a coin with a value in cents stored right on each constant.
public enum Coin { PENNY(1), NICKEL(5), DIME(10), QUARTER(25);
private final int cents; // a field on every constant
Coin(int cents) { // the constructor (private by default) this.cents = cents; }
public int getCents() { // a method every constant can use return cents; }}Read it from the top.
- Each constant has parentheses with a number, like
PENNY(1). That number is passed to the constructor. - The constructor stores it in
cents. ThegetCents()method reads it back. - An enum constructor is always private, so you cannot call
new Coin(...)from outside. Java calls it once per constant.
This program adds up a handful of coins.
public class Wallet { public static void main(String[] args) { Coin[] pocket = { Coin.QUARTER, Coin.DIME, Coin.PENNY };
int total = 0; for (Coin c : pocket) { System.out.println(c.name() + " = " + c.getCents() + " cents"); total += c.getCents(); } System.out.println("Total: " + total + " cents"); }}Output
QUARTER = 25 centsDIME = 10 centsPENNY = 1 centsTotal: 36 centsThe value is tied to the constant. You never pass 25 around by hand. You say Coin.QUARTER, and the worth comes along.
๐ช A bigger example: Planet with data and a calculation
Each constant can hold more than one field, and a method can do real math with them. Here every planet knows its mass and radius, and works out its surface gravity.
public enum Planet { MERCURY(3.30e23, 2.44e6), EARTH(5.97e24, 6.37e6), JUPITER(1.90e27, 7.15e7);
private final double mass; // in kilograms private final double radius; // in meters
Planet(double mass, double radius) { this.mass = mass; this.radius = radius; }
private static final double G = 6.67e-11;
public double gravity() { return G * mass / (radius * radius); }
public double weightOf(double earthWeight) { double mass = earthWeight / EARTH.gravity(); return mass * gravity(); }}Each constant carries mass and radius. The gravity() method turns those into surface gravity, and weightOf reuses it to convert an Earth weight to another planet. This prints what someone who weighs 700 on Earth would weigh elsewhere.
public class Trip { public static void main(String[] args) { double earthWeight = 700.0; for (Planet p : Planet.values()) { System.out.printf("On %-8s you weigh %.0f%n", p.name(), p.weightOf(earthWeight)); } }}Output
On MERCURY you weigh 265On EARTH you weigh 700On JUPITER you weigh 1768All the data and logic live inside the enum, so the calling code stays short. This is what people mean when they say an enum carries behavior, not just a name.
๐งฎ Constant-specific method bodies
Sometimes each constant needs its own version of the same method. A math operation is the perfect case. PLUS and MINUS both have an apply step, but the step differs. Java lets each constant override an abstract method with its own 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; } }, TIMES { public int apply(int a, int b) { return a * b; } };
public abstract int apply(int a, int b);}The enum declares an abstract method apply. Each constant follows its name with braces and gives its own body. So PLUS adds, MINUS subtracts, TIMES multiplies. This runs every operation on the same pair of numbers.
public class Calc { public static void main(String[] args) { int a = 6, b = 2; for (Operation op : Operation.values()) { System.out.println(a + " " + op + " " + b + " = " + op.apply(a, b)); } }}Output
6 PLUS 2 = 86 MINUS 2 = 46 TIMES 2 = 12This is cleaner than a long switch. The behavior sits next to the constant, and the abstract method forces every new operation to give an apply body.
๐๏ธ EnumMap and EnumSet, in brief
Java ships two special collections built just for enums. They are fast and tidy because they know the keys are enum constants. An EnumMap is a map whose keys are enum values. This maps each day to a task.
import java.util.EnumMap;
public class Planner { public static void main(String[] args) { EnumMap<Day, String> tasks = new EnumMap<>(Day.class); tasks.put(Day.MONDAY, "Plan the week"); tasks.put(Day.FRIDAY, "Review and rest");
System.out.println(tasks); }}Output
{MONDAY=Plan the week, FRIDAY=Review and rest}An EnumSet is a set that holds enum values, a compact way to store a group of constants. This builds a set of work days.
import java.util.EnumSet;
public class Week { public static void main(String[] args) { EnumSet<Day> workdays = EnumSet.of(Day.MONDAY, Day.WEDNESDAY, Day.FRIDAY); System.out.println("Is Wednesday a workday? " + workdays.contains(Day.WEDNESDAY)); System.out.println(workdays); }}Output
Is Wednesday a workday? true{MONDAY, WEDNESDAY, FRIDAY}Both keep entries in declaration order, and both beat HashMap or HashSet for enum keys. Reach for them whenever your keys or members are enum constants.
โ ๏ธ Common Mistakes
Trying to make the enum constructor public. It will not compile. Java creates the constants for you.
// โ Wrong: an enum constructor cannot be publicpublic enum Coin { PENNY(1); public Coin(int cents) { } // compile error}// โ
Right: leave it package-private or write privatepublic enum Coin { PENNY(1); private Coin(int cents) { }}Relying on ordinal() for real meaning, like saving it in a database. The number is just the position. Reorder or insert a constant, and every stored number points to the wrong one.
// โ Wrong: storing ordinal, which breaks if the order changesint saved = Coin.DIME.ordinal(); // happens to be 2 today// โ
Right: store the stable name insteadString saved = Coin.DIME.name(); // always "DIME"Coin back = Coin.valueOf(saved);Calling valueOf with text that matches no constant. It throws IllegalArgumentException, and a stray space or wrong case is enough to break it.
// โ Wrong: "monday" is lower case, so it does not match MONDAYDay d = Day.valueOf("monday");Output
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant Day.monday// โ
Right: normalize the text, or guard against bad inputDay d = Day.valueOf("monday".toUpperCase()); // "MONDAY"โ Best Practices
- Make fields
finaland set them in the constructor. An enum constant is a fixed value, so its data should not change. - Store and compare by
name(), notordinal(). The name is stable across reorders. The position is not. - Wrap risky
valueOfcalls. If the text comes from a user or file, trim it, fix the case, and handle a bad value. - Put behavior on the enum. If each constant needs its own logic, use constant-specific method bodies, not a far-away
switch. - Use
EnumMapandEnumSetfor enum keys and members. They are faster and read better than the general collections.
๐ง What youโve learned
An enum is far more than a list of names. Every enum gives you values(), valueOf(String), name(), ordinal(), and compareTo() for free. You can add fields, a private constructor, and methods so each constant carries its own data and behavior, like a Coin with a value or a Planet that computes gravity. You can give each constant its own method body with an abstract method, the way Operation does for apply. And you have EnumMap and EnumSet for enums in collections. The big rule: lean on name() and valueOf(), and stay away from ordinal() for anything that matters.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What does the built-in values() method return?
Why: values() returns an array holding every constant, in the order you declared them.
- 2
What is the access level of an enum constructor?
Why: An enum constructor is always private. Java calls it for you to build each constant.
- 3
Why should you avoid storing ordinal() values?
Why: ordinal() is just the position in the list, so it breaks the moment the order changes. Store name() instead.
- 4
What happens when valueOf() gets text that matches no constant?
Why: valueOf() is strict. A name that does not match exactly throws IllegalArgumentException.
๐ Whatโs Next?
You have seen how to give enums real data and behavior. Next, letโs look at another way Java lets you nest one type inside another. Sometimes a small helper class only makes sense inside the class that uses it. Those are called inner classes, and they keep related code close together. Letโs learn them.