4.2 Enumerations: Constants, Constructors, Methods, and Custom Bodies

Key Takeaways

  • Enum types implicitly extend java.lang.Enum<E> and are implicitly final, or implicitly sealed when a constant declares a class body, so no outside class can extend them while they can still implement interfaces.

  • Enum constructors are implicitly private, executed once per constant during enum class initialization, and can never be invoked via new or reflection.

  • Constants must be declared first before any fields or methods; a terminating semicolon is mandatory only if additional members or constant bodies are present.

  • Constant-specific class bodies allow individual constants to override methods or implement abstract methods declared in the enum header.

  • Standard enum methods include values() (which returns a defensive copy array), valueOf(String), name(), and ordinal(); name() and ordinal() are final and cannot be overridden.

Last updated: October 2026

Enumerations: Constants, Constructors, Methods, and Custom Bodies

An enumeration (enum) in Java is a specialized reference type representing a fixed set of named constant instances. Far from being simple integer aliases like enums in C or C++, Java enums are full-featured classes that can encapsulate fields, constructors, business methods, and constant-specific logic. The Oracle 1Z0-829 exam tests the precise lifecycle, constructor semantics, structural constraints, and polymorphism mechanics unique to enum types.


1. Enum Declaration and Class Architecture

An enum is defined using the enum keyword. Behind the scenes, the compiler transforms an enum into a class with specific architectural properties:

public enum Direction {
    NORTH, SOUTH, EAST, WEST
}

Compiler-Generated Properties of Enums

  1. Implicit Superclass: Every enum implicitly extends java.lang.Enum<E>. Because Java enforces single class inheritance, an enum cannot extend any other class (enum Day extends Calendar fails compilation).
  2. Implicit Modifiers: An enum is implicitly final unless at least one constant has a class body, in which case Java 17 makes it implicitly sealed (permitting only those constant bodies). Writing abstract or final on an enum declaration yourself is a compile error. In every case, an enum cannot be subclassed by an external class.
  3. Interface Implementation: Although an enum cannot extend any class, it can implement one or more interfaces (enum Direction implements Navigable, Serializable).

Semicolon and Member Ordering Rules

  • Order of Members: The enum constants must be declared first, before any instance fields, static variables, constructors, or methods.
  • Semicolon Usage:
    • If the enum contains only constants and no other members, the trailing semicolon is completely optional:
      enum Status { OPEN, CLOSED } // Valid
      enum Status { OPEN, CLOSED; } // Also valid
      
    • If the enum defines any additional members (fields, constructors, methods) or if constants define constant-specific class bodies, a semicolon after the constant list is strictly mandatory:
      enum Status {
          OPEN, CLOSED; // Semicolon required here!
          private final int code = 1;
      }
      

Warning

Placing a field or method before the enum constants (e.g., private int id; OPEN, CLOSED;) is a compile-time error: the constant list must be the first thing in the enum body.


2. Enum Constructors and Initialization Lifecycle

Enums can declare constructors to initialize fields associated with each constant.

public enum Currency {
    USD(1.0), EUR(1.1), JPY(0.007);

    private final double exchangeRate;

    Currency(double rate) { // Implicitly private
        this.exchangeRate = rate;
    }

    public double getExchangeRate() { return exchangeRate; }
}

Constructor Rules and Modifiers

  • Access Modifier: Enum constructors are implicitly private. The only permitted explicit modifier is private. Declaring an enum constructor as public or protected causes a compilation error: modifier public/protected not allowed here.
  • Cannot Use new: Enum instances are created exclusively by the JVM when the enum type is initialized. Directly calling new Currency(1.0) is a compile-time error: enum types may not be instantiated.
  • Reflection Safety: Attempting to instantiate an enum via reflection (Constructor.newInstance()) throws an IllegalArgumentException: Cannot reflectively create enum objects. Enums are fundamentally protected against multiple instantiation.

Execution Lifecycle Order

When an enum class is first referenced (e.g., accessing any constant or static method), the JVM initializes the enum. During this initialization, constructors execute for every declared constant in order of declaration before any static members or main method statements execute.

enum Signal {
    RED("Stop"), YELLOW("Caution"), GREEN("Go");

    Signal(String action) {
        System.out.print(action + " ");
    }
}

public class SignalTest {
    public static void main(String[] args) {
        System.out.print("Start: ");
        Signal s = Signal.RED;
    }
}

Output: Start: Stop Caution Go Referencing Signal.RED triggers the initialization of the entire Signal class, executing the constructor for RED, then YELLOW, and then GREEN sequentially.


3. Constant-Specific Class Bodies and Abstract Methods

Java enums support constant-specific class bodies, allowing each constant to provide distinct implementations of methods.

Overriding Concrete Methods

public enum Operation {
    PLUS {
        @Override
        public double apply(double x, double y) { return x + y; }
    },
    MINUS {
        @Override
        public double apply(double x, double y) { return x - y; }
    },
    MULTIPLY; // Inherits default apply

    public double apply(double x, double y) {
        return 0.0;
    }
}

Abstract Methods in Enums

An enum can declare an abstract method. If an enum defines an abstract method:

  • The enum class itself is not explicitly marked abstract (the compiler handles this implicitly).
  • Every constant MUST implement the abstract method in its constant-specific class body. If even one constant fails to implement it, compilation fails.
public enum Calculation {
    ADD {
        public int compute(int a, int b) { return a + b; }
    },
    SUBTRACT {
        public int compute(int a, int b) { return a - b; }
    }; // Both constants implement compute

    public abstract int compute(int a, int b); // Abstract method declaration
}

Under the hood, each constant with a class body compiles to an anonymous subclass extending the outer enum class.


4. Standard Enum Methods

Every enum inherits from java.lang.Enum<E> and receives synthetic methods generated by the compiler.

MethodReturn TypeDescriptionOverridable?
values()E[]Returns a newly cloned array containing all constants in order of declarationSynthetic (No)
valueOf(String name)EReturns the constant with the matching name. Throws IllegalArgumentException if not foundSynthetic (No)
name()StringReturns the exact declared name of the constantfinal (No)
ordinal()intReturns the zero-based position of the constant in the declaration listfinal (No)
toString()StringReturns name() by default, but can be overridden for user-friendly outputYes
compareTo(E o)intCompares constants based on their declaration ordinal() orderfinal (No)
equals(Object o)booleanCompares reference identity (this == o)final (No)

Key Caveats for the Exam

  • values() creates a defensive copy: Each call to Enum.values() allocates a brand-new array. Mutating the returned array (values[0] = null;) does not corrupt the internal enum constants.
  • name() vs. toString(): name() is final and guaranteed to return the exact identifier declared in source code. toString() can be overridden to return arbitrary strings.
  • ordinal() Fragility: Avoid using ordinal() for business logic or persistence, as reordering or inserting constants changes the ordinal values.

5. Enums in Switch Statements and Expressions

Enums integrate seamlessly with both traditional switch statements and modern Java 17 switch expressions.

The Unqualified Name Rule in Switch Labels

When switching over an enum variable, the case labels must use the unqualified simple name of the constant. Qualifying the constant with the enum class name causes a compilation error:

Direction dir = Direction.NORTH;
switch (dir) {
    case NORTH -> System.out.println("Heading North"); // COMPILES: Unqualified name
    // case Direction.SOUTH -> System.out.println("South"); // COMPILE ERROR: an enum switch case label must be the unqualified name of an enumeration constant
    default -> System.out.println("Other");
}

Exhaustiveness in Switch Expressions

In Java 17 switch expressions, if every constant of the enum is explicitly handled, the default clause can be omitted entirely:

String action = switch (dir) {
    case NORTH -> "Up";
    case SOUTH -> "Down";
    case EAST  -> "Right";
    case WEST  -> "Left";
}; // Fully exhaustive: no default branch needed!

If any constant is left unhandled and no default branch exists, the compiler flags an error: the switch expression does not cover all possible input values.

Test Your Knowledge

Consider the following program:

enum SpeedLimit {
    CITY(30), HIGHWAY(65), AUTOBAHN(0);
    
    SpeedLimit(int limit) {
        System.out.print(limit + " ");
    }
}

public class RoadTest {
    public static void main(String[] args) {
        System.out.print("Drive:");
        SpeedLimit sp = SpeedLimit.AUTOBAHN;
        System.out.print(":" + sp.name());
    }
}

What does this program output when executed?

A

Drive:0:AUTOBAHN

B

30 65 0 Drive::AUTOBAHN

C

Drive:AUTOBAHN:0

D

Drive:30 65 0 :AUTOBAHN

Test Your Knowledge

Examine the following code snippet:

enum TrafficMode { DRIVE, PARK }

public class VehicleController {
    public void control(TrafficMode mode) {
        switch (mode) {
            case TrafficMode.DRIVE:
                System.out.println("Moving");
                break;
            case PARK:
                System.out.println("Stationary");
                break;
        }
    }
}

What is the result of attempting to compile this class?

A

The class compiles successfully and outputs the state based on the provided mode.

B

Compilation fails because mode cannot be used as an argument to a switch statement without calling ordinal().

C

Compilation fails because the switch statement does not include a default case.

D

Compilation fails because case labels for enum switches must be unqualified constant names.

Test Your Knowledge

Given the following enum definition:

public enum Protocol {
    TCP {
        public int getDefaultPort() { return 80; }
    },
    UDP;

    public abstract int getDefaultPort();
}

What is the compilation result for Protocol?

A

Compilation fails because constant UDP does not implement the abstract method getDefaultPort().

B

Protocol compiles successfully because UDP inherits 0 as the default port.

C

Compilation fails because enum classes cannot declare abstract methods.

D

Compilation fails because TCP cannot define a public method in a constant-specific class body.

Sections you finish are checked off in the contents.