Java Language Declaring and using a basic enum


Example

Enum can be considered to be syntax sugar for a sealed class that is instantiated only a number of times known at compile-time to define a set of constants.

A simple enum to list the different seasons would be declared as follows:

public enum Season {
    WINTER,
    SPRING,
    SUMMER,
    FALL
}

While the enum constants don't necessarily need to be in all-caps, it is Java convention that names of constants are entirely uppercase, with words separated by underscores.


You can declare an Enum in its own file:

/**
 * This enum is declared in the Season.java file.
*/
public enum Season {
    WINTER,
    SPRING,
    SUMMER,
    FALL
}

But you can also declare it inside another class:

 public class Day {

    private Season season;

    public String getSeason() {
        return season.name();
    }

    public void setSeason(String season) {
        this.season = Season.valueOf(season);
    }

    /**
     * This enum is declared inside the Day.java file and 
     * cannot be accessed outside because it's declared as private.
     */
    private enum Season {
        WINTER,
        SPRING,
        SUMMER,
        FALL
    }

}

Finally, you cannot declare an Enum inside a method body or constructor:

public class Day {

    /**
     * Constructor
    */
    public Day() {
        // Illegal. Compilation error
        enum Season {
            WINTER,
            SPRING,
            SUMMER,
            FALL
        }
    }

    public void aSimpleMethod() {
        // Legal. You can declare a primitive (or an Object) inside a method. Compile!
        int primitiveInt = 42;

        // Illegal. Compilation error.
        enum Season {
            WINTER,
            SPRING,
            SUMMER,
            FALL
        }

        Season season = Season.SPRING;
    }
    
}

Duplicate enum constants are not allowed:

public enum Season {
    WINTER,
    WINTER, //Compile Time Error : Duplicate Constants
    SPRING,
    SUMMER,
    FALL
} 

Every constant of enum is public, static and final by default. As every constant is static, they can be accessed directly using the enum name.

Enum constants can be passed around as method parameters:

public static void display(Season s) {
    System.out.println(s.name());  // name() is a built-in method that gets the exact name of the enum constant
}

display(Season.WINTER);  // Prints out "WINTER"

You can get an array of the enum constants using the values() method. The values are guaranteed to be in declaration order in the returned array:

Season[] seasons = Season.values();

Note: this method allocates a new array of values each time it is called.


To iterate over the enum constants:

public static void enumIterate() {
    for (Season s : Season.values()) {
        System.out.println(s.name());
    }
}

You can use enums in a switch statement:

public static void enumSwitchExample(Season s) {
    switch(s) {
        case WINTER:
            System.out.println("It's pretty cold");
            break;
        case SPRING:
            System.out.println("It's warming up");
            break;
        case SUMMER:
            System.out.println("It's pretty hot");
            break;
        case FALL:
            System.out.println("It's cooling down");
            break;
    }
}

You can also compare enum constants using ==:

Season.FALL == Season.WINTER    // false
Season.SPRING == Season.SPRING  // true

Another way to compare enum constants is by using equals() as below, which is considered bad practice as you can easily fall into pitfalls as follows:

Season.FALL.equals(Season.FALL); // true
Season.FALL.equals(Season.WINTER); // false
Season.FALL.equals("FALL"); // false and no compiler error

Furthermore, although the set of instances in the enum cannot be changed at run-time, the instances themselves are not inherently immutable because like any other class, an enum can contain mutable fields as is demonstrated below.

public enum MutableExample {
    A,
    B;

    private int count = 0;

    public void increment() {
        count++;
    }

    public void print() {
        System.out.println("The count of " + name() + " is " + count);
    }
}

// Usage:
MutableExample.A.print();       // Outputs 0
MutableExample.A.increment();
MutableExample.A.print();       // Outputs 1 -- we've changed a field   
MutableExample.B.print();       // Outputs 0 -- another instance remains unchanged

However, a good practice is to make enum instances immutable, i.e. when they either don't have any additional fields or all such fields are marked as final and are immutable themselves. This will ensure that for a lifetime of the application an enum won't leak any memory and that it is safe to use its instances across all threads.


Enums implicitly implement Serializable and Comparable because the Enum class does:

public abstract class Enum<E extends Enum<E>>
extends Object
implements Comparable<E>, Serializable