Java Enum Tutorial

by Dimitris Tasios
704 views

In this tutorial, we are going to learn about enum in Java, and how to use them, through examples.

1. What is an Enum in Java?

Enums (enumerations) are special classes in Java that represent a group of constants. For instance, we could have an enum of months, points of direction, colours, or anything else that represents a collection of fixed values.

Internally, an enum value extends the Enum class and is defined as a static, final class. Being a static class means that it can be used without creating an instance of the class, and being final means that it cannot be extended any further into subclasses. Despite extending the Enum class, they can implement interfaces normally, and even define their own, which we’ll see later down below.

2. A Simple Example of an Enum in Java

Let’s take a look at how to create an enum. An enum can either be a part of a class or separate. In both cases, the syntax is similar; it mostly depends on how we are going to use them. So, you should ask yourself the following questions:

  • Is it a specific-purpose enum that only makes sense to exist within a class? Then go with an inner-class enum.
  • Will the enum be useful to more classes? In that case, an outer enum would be more useful.

Let’s see the example:

// define an outer enum of the people who can may eat an ice cream.
enum Person {
    DIMITRIS, AKIS, IGNIS;
}

public class EnumIceCreamExampleClass {

    // define an inner enum representing ice cream flavours
    enum IceCreamFlavour {
        // By Java convention, enum values are written in all capital letters
        VANILLA, CHOCOLATE, STRAWBERRY, BANANA;
    }

    public static void main(String[] args) {
        // choose banana flavour
        IceCreamFlavour iceCream = IceCreamFlavour.BANANA;

        // choose who can eat the ice cream
        Person personWithIceCream = Person.DIMITRIS;

        // the following cannot be written; Enums cannot be instantiated because they do not have a public constructor
//        Person invalidPerson = new Person();

        // printing the enum will print its name
        System.out.println(personWithIceCream + " is eating a " + iceCream + " ice cream");
    }
}

Output

DIMITRIS is eating a BANANA ice cream

In the example above we define two enums; Person and IceCreamFlavour. The former enum defines a person who may eat ice cream while the latter defines the flavour of ice cream that a Person chose.

In our example, Person is defined outside of the EnumIceCreamExampleClass class while IceCreamFlavour is part of the class. Perhaps we want to use the same Person enum with other enums, like who wants to go to some specific European countries or make a list about movie genre preferences for each person.

As you can see, there is no need to instantiate an enum with the new keyword. In fact, it’s not possible to do that (line 22), because constructors in enums must be private. If not declared explicitly, they will be considered private. Nevertheless, we can still create our own constructors for an enum (more of that later).

3. What Can You Do With Enums?

In this section, we will see what a Java Enum is capable of, with the help of its methods. In the examples below we will be using the following enum, IceCreamFlavour, representing flavours of ice cream available in a store. If this enum needs to updated for the sake of the examples, it will be redefined in that example. Otherwise, if it’s not included in the example, assume that the enum is the following (for the sake of brevity):

    // define an enum representing ice cream flavours
    enum IceCreamFlavour {

        // each flavour has an integer representing the number of scoops allowed for each flavour, due to availability
        VANILLA, CHOCOLATE, STRAWBERRY, BANANA;
    }

3.1 Enum Fields by using a Constructor

We can create (private) constructors that initialize each enum value with a value. This value can be changed later.

public class EnumMethodsAndCapabilitiesExampleClass {
    // define an enum representing ice cream flavours
    enum IceCreamFlavour {

        // each flavour has an integer representing the number of scoops allowed for each flavour, due to availability
        VANILLA(2), CHOCOLATE(3), STRAWBERRY(1), BANANA(1);

        // declare a variable for each flavour. It's not necessary to be private and/or final.
        private int scoopsOfIceCream;

        // constructor is private by default
        IceCreamFlavour(int scoops) {
            this.scoopsOfIceCream = scoops;
        }
    }

    private static void enumConstructor() {
        System.out.println("----------------------start of enumConstructor()----------------------\n");
        // create a chocolate ice cream
        IceCreamFlavour chocolateIceCream = IceCreamFlavour.CHOCOLATE;

        // print our choice
        System.out.println("I choose " + chocolateIceCream);

        // default scoops given for chocolate ice creams
        System.out.println("Initially, I was given " + chocolateIceCream.scoopsOfIceCream + " scoops of " + chocolateIceCream + " ice cream");

        // ask for more
        chocolateIceCream.scoopsOfIceCream += 2;

        // print our total scoops now
        System.out.println("After asking for more, I now have " + chocolateIceCream.scoopsOfIceCream + " scoops of " + chocolateIceCream + " ice cream");
        System.out.println("\n-----------------------end of enumConstructor()-----------------------\n");
    }

    public static void main(String[] args) {
        enumConstructor();

    }
}

Output

----------------------start of enumConstructor()----------------------

I choose CHOCOLATE
Initially, I was given 3 scoops of CHOCOLATE ice cream
After asking for more, I now have 5 scoops of CHOCOLATE ice cream

-----------------------end of enumConstructor()-----------------------

In the example above, each flavour of ice cream is offered with a predetermined number of scoops. We can, however, change this number, as shown in line 29.

3.2 Using Java Enum in If Statements

If we want to check whether a value is equal to an enum value, we can do that with the “==” operator.

As told above, assume that the enum is the simple version of the IceCreamFlavour, defined at the beginning of section 3.

    private static void enumIfStatements() {
        System.out.println("----------------------start of enumIfStatements()----------------------\n");
        // create an ice cream flavour
        IceCreamFlavour myFlavour = IceCreamFlavour.CHOCOLATE;

        if(myFlavour == IceCreamFlavour.VANILLA) {
            System.out.println("This is vanilla ice cream!");
        } else if(myFlavour == IceCreamFlavour.CHOCOLATE) {
            System.out.println("This is chocolate ice cream!");
        } else if(myFlavour == IceCreamFlavour.STRAWBERRY) {
            System.out.println("This is strawberry ice cream!");
        } else if(myFlavour == IceCreamFlavour.BANANA) {
            System.out.println("This is banana ice cream!");
        }
        System.out.println("\n-----------------------end of enumIfStatements()-----------------------\n");
    }

Output

----------------------start of enumIfStatements()----------------------

This is chocolate ice cream!

-----------------------end of enumIfStatements()-----------------------

3.3 Using Java Enum in Switch Statements

Because of how easy enums are to read, the example above could be written in a much clearer way, by using a switch statement instead.

    private static void enumSwitchStatements() {
        System.out.println("----------------------start of enumSwitchStatements()----------------------\n");
        // create an ice cream flavour
        IceCreamFlavour myFlavour = IceCreamFlavour.CHOCOLATE;

        switch (myFlavour) {
            case VANILLA:
                System.out.println("This is vanilla ice cream!");
                break;
            case CHOCOLATE:
                System.out.println("This is chocolate ice cream!");
                break;
            case STRAWBERRY:
                System.out.println("This is strawberry ice cream!");
                break;
            case BANANA:
                System.out.println("This is banana ice cream!");
                break;
        }

        System.out.println("\n-----------------------end of enumSwitchStatements()-----------------------\n");
    }

Output

----------------------start of enumSwitchStatements()----------------------

This is chocolate ice cream!

-----------------------end of enumSwitchStatements()-----------------------

3.4 Looping Through All Enum Using the values() Method

We can loop through all values in an enum with the help of the values() method. This method returns an Array of the same enum type. Because of that, we can you both a normal loop as well as an enhanced loop, as such:

    private static void enumLoopWithValues() {
        System.out.println("----------------------start of enumLoopWithValues()----------------------\n");

        System.out.println("Our available ice cream flavours are:\n");

        System.out.println("Using an ordinary for loop");
        for(int i = 0; i < IceCreamFlavour.values().length; i++) {
            System.out.println(IceCreamFlavour.values()[i]);
        }

        System.out.println("\nUsing an enchanced for loop");
        for(IceCreamFlavour flavour : IceCreamFlavour.values()) {
            System.out.println(flavour);
        }

        System.out.println("\n-----------------------end of enumLoopWithValues()-----------------------\n");
    }

Output

----------------------start of enumLoopWithValues()----------------------

Our available ice cream flavours are:

Using an ordinary for loop
VANILLA
CHOCOLATE
STRAWBERRY
BANANA

Using an enchanced for loop
VANILLA
CHOCOLATE
STRAWBERRY
BANANA

-----------------------end of enumLoopWithValues()-----------------------

3.5 Getting the Value of an Enum With valueOf(String name)

If we want to get the exact value of an enum, we can use the valueOf(String name). If the enum has a value equal to “name” then it will be returned otherwise, an IllegalArgumentException exception will be thrown.

    private static void enumValueOf() {
        System.out.println("----------------------start of enumValueOf()----------------------\n");

        // ask whether the store offers strawberry ice creams
        System.out.println("-Do you have strawberry ice cream?");
        requestIceCreamFlavour("STRAWBERRY");

        // now ask about stracciatella ice creams
        System.out.println("\n-Do you also have stracciatella ice cream?");
        requestIceCreamFlavour("STRACCIATELLA");

        System.out.println("\n-----------------------end of enumValueOf()-----------------------\n");
    }

    private static void requestIceCreamFlavour(String name) {
        try {
            IceCreamFlavour requestedFlavour = IceCreamFlavour.valueOf(name);
            System.out.println("-Yes, we offer " + requestedFlavour + " ice cream!");
        } catch (IllegalArgumentException exception) {
            System.out.println("-I'm sorry but we do not offer " + name + " ice cream.");
        }
    }

Output

----------------------start of enumValueOf()----------------------

-Do you have strawberry ice cream?
-Yes, we offer STRAWBERRY ice cream!

-Do you also have stracciatella ice cream?
-I'm sorry but we do not offer STRACCIATELLA ice cream.

-----------------------end of enumValueOf()-----------------------

To avoid duplication, we have defined the requestIceCreamFlavour(String name) method, which checks for the requested flavour in the IceCreamFlavour enum.

In order to not crash during execution, we used a try/catch block, in case the aforementioned exception was thrown. As you can see, when the flavour exists in the IceCreamFlavour enum, the execution flows normally, through the try block only. Otherwise, we are led to the catch block, indicating an unavailable ice cream flavour, in our case.

3.6 Get the index of Enum with ordinal()

If we want to know the order of the values of an enum, we can use the ordinal() method, which returns an Int indicating the value’s order in the enum.

    private static void enumOrdinal() {
        System.out.println("----------------------start of enumOrdinal()----------------------\n");

        // ask in which position vanilla is, because we cannot read the sign in the language they are written
        System.out.println("-Excuse me, which flavour is Vanilla?");

        // position of vanilla's container, as displayed in front of us
        int vanillaIndex = IceCreamFlavour.VANILLA.ordinal();

        // vendor's response
        switch (vanillaIndex) {
            case 0:
                System.out.println("-It's the first one!");
                break;
            case 1:
                System.out.println("-It's the second one!");
                break;
            case 2:
                System.out.println("-It's the third one!");
                break;
            case 3:
                System.out.println("-It's the fourth one!");
                break;
            default:
                break;
        }

        System.out.println("\n-----------------------end of enumOrdinal()-----------------------\n");
    }

Output

----------------------start of enumOrdinal()----------------------

-Excuse me, which flavour is Vanilla?
-It's the first one!

-----------------------end of enumOrdinal()-----------------------

3.7 Add Functionalities in Enum Through Methods

We can add methods inside an enum, enriching its functionality. We may also add abstract methods, which must be implemented by each enum value.

3.7.1 Ordinary Enum Methods

It is possible to add methods inside an enum. The complexity of those methods is totally up to us; they can range from simple printing or getters/setters to methods that perform complicated calculations.

public class EnumOrdinaryMethodsExampleClass {
    enum IceCreamFlavour {

        // each flavour has an integer representing the number of scoops allowed for each flavour, due to availability
        VANILLA(2),
        CHOCOLATE(3),
        STRAWBERRY(1),
        BANANA(1);

        // declare a variable for each flavour. It's not necessary to be private and/or final.
        private int scoopsOfIceCream;

        // constructor is private by default
        IceCreamFlavour(int scoops) {
            this.scoopsOfIceCream = scoops;
        }

        // announce the flavour and scoops of the enum value. "this" refers to the current enum value
        void announceFlavourAndScoops() {
            System.out.println("For " + this + " flavour, there are " + this.scoopsOfIceCream + " available scoops.");
        }
    }

    private static void enumOrdinaryMethod() {
        System.out.println("----------------------start of enumOrdinaryMethod()----------------------\n");

        IceCreamFlavour[] allFlavours = IceCreamFlavour.values();

        // announce 10 random flavours with random number of scoops each
        for(int i = 0; i < 10; i++) {

            // get a random flavour index
            int flavourIndex = (int) (0 + Math.random() * (4 - 0));

            // get the flavour at the specified index
            IceCreamFlavour chosenFlavour = allFlavours[flavourIndex];

            // get a random number of scoops from 1 to 5
            int numberOfScoops = (int) (1 + Math.random() * (6 - 1));

            // set the number of scoops to the flavour
            chosenFlavour.scoopsOfIceCream = numberOfScoops;

            // announce the result
            chosenFlavour.announceFlavourAndScoops();
        }

        System.out.println("\n-----------------------end of enumOrdinaryMethod()-----------------------\n");
    }

    public static void main(String[] args) {
        enumOrdinaryMethod();
    }
}

In the snippet above, we have enriched our enum with the announceFlavourAndScoops() method, which simply prints the enum value’s flavour and the number of scoops.

Then in enumOrdinaryMethod() we generate 10 random flavour/scoops combinations and announce the result each time.

Output

----------------------start of enumOrdinaryMethod()----------------------

For CHOCOLATE flavour, there are 2 available scoops.
For BANANA flavour, there are 2 available scoops.
For CHOCOLATE flavour, there are 5 available scoops.
For STRAWBERRY flavour, there are 5 available scoops.
For VANILLA flavour, there are 4 available scoops.
For BANANA flavour, there are 5 available scoops.
For STRAWBERRY flavour, there are 4 available scoops.
For CHOCOLATE flavour, there are 3 available scoops.
For CHOCOLATE flavour, there are 4 available scoops.
For BANANA flavour, there are 1 available scoops.

-----------------------end of enumOrdinaryMethod()-----------------------

3.7.2 Abstract Methods in Enum

By declaring and implementing abstract methods, enum values can have unique behaviour, under the same “contract”, the abstract method’s signature. Then we can use those methods normally, as the methods in the section above.

public class EnumAbstractMethodsExampleClass {
    enum IceCreamFlavour {

        VANILLA {
            @Override
            void translateToSpanishAndAnnounce() {
                System.out.println("Español: Esto es helado de VAINILLA.");
            }

            @Override
            void announceInEnglish() {
                System.out.println("English: This is VANILLA ice cream.");
            }
        },
        CHOCOLATE {
            @Override
            void translateToSpanishAndAnnounce() {
                System.out.println("Español: Esto es helado de CHOCOLATE.");
            }

            @Override
            void announceInEnglish() {
                System.out.println("English: This is CHOCOLATE ice cream.");
            }
        },
        STRAWBERRY {
            @Override
            void translateToSpanishAndAnnounce() {
                System.out.println("Español: Esto es helado de FRESCA.");
            }

            @Override
            void announceInEnglish() {
                System.out.println("English: This is STRAWBERRY ice cream.");
            }
        },
        BANANA {
            @Override
            void translateToSpanishAndAnnounce() {
                System.out.println("Español: Esto es helado de PLÁTANO.");
            }

            @Override
            void announceInEnglish() {
                System.out.println("English: This is BANANA ice cream.");
            }
        };

        abstract void translateToSpanishAndAnnounce();
        abstract void announceInEnglish();
    }

    private static void enumAbstractMethod() {
        System.out.println("----------------------start of enumAbstractMethod()----------------------\n");

        // announce all flavours in English and Spanish
        for(IceCreamFlavour flavour : IceCreamFlavour.values()) {
            flavour.announceInEnglish();
            flavour.translateToSpanishAndAnnounce();
            System.out.println();
        }

        System.out.println("\n-----------------------end of enumAbstractMethod()-----------------------\n");
    }

    public static void main(String[] args) {
        enumAbstractMethod();
    }
}

In the method above, we define two abstract methods that announce the current flavour; one in English and one in Spanish (lines 49-50). Each ice cream flavour (enum value) must implement those two methods. As you can see, each flavour implements those methods a bit differently from the rest, because they each would have to announce their respective flavour in both languages.

Then, in enumAbstractMethod(), we simply call those two methods (lines 58-59) for each flavour.

Output

----------------------start of enumAbstractMethod()----------------------

English: This is VANILLA ice cream.
Español: Esto es helado de VAINILLA.

English: This is CHOCOLATE ice cream.
Español: Esto es helado de CHOCOLATE.

English: This is STRAWBERRY ice cream.
Español: Esto es helado de FRESCA.

English: This is BANANA ice cream.
Español: Esto es helado de PLÁTANO.


-----------------------end of enumAbstractMethod()-----------------------

4. Conclusion

In conclusion, you should now be able to take full advantage of Java’s powerful Enum class. You can find the source code on our GitHub page.

5. Sources

[1]: Enum Types – Oracle

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.

Related Posts