Java Enum Methods

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 0
TUESDAY is at index 1
WEDNESDAY is at index 2
THURSDAY is at index 3
FRIDAY is at index 4
Got: FRIDAY
-4

Each 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. So Day.MONDAY.name() is "MONDAY".
  • ordinal() returns the position, counting from zero. MONDAY is 0. Be careful with this one (more later).
  • valueOf(String) is the reverse of name(). Text in, matching constant out.
  • compareTo() compares two constants by declaration order. MONDAY.compareTo(FRIDAY) is 0 - 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: WEDNESDAY
Loaded: WEDNESDAY
Same value? true

The == 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. The getCents() 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 cents
DIME = 10 cents
PENNY = 1 cents
Total: 36 cents

The 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 265
On EARTH you weigh 700
On JUPITER you weigh 1768

All 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 = 8
6 MINUS 2 = 4
6 TIMES 2 = 12

This 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 public
public enum Coin {
PENNY(1);
public Coin(int cents) { } // compile error
}
// โœ… Right: leave it package-private or write private
public 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 changes
int saved = Coin.DIME.ordinal(); // happens to be 2 today
// โœ… Right: store the stable name instead
String 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 MONDAY
Day 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 input
Day d = Day.valueOf("monday".toUpperCase()); // "MONDAY"

โœ… Best Practices

  • Make fields final and set them in the constructor. An enum constant is a fixed value, so its data should not change.
  • Store and compare by name(), not ordinal(). The name is stable across reorders. The position is not.
  • Wrap risky valueOf calls. 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 EnumMap and EnumSet for 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. 1

    What does the built-in values() method return?

    Why: values() returns an array holding every constant, in the order you declared them.

  2. 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. 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. 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.

Java Inner Classes

Share & Connect