Zach Cochran
by Zach Cochran
4 min read

Categories

Tags

Today we’re going to talk a bit about enums.

When I started learning Java, enums were completely foreign to me. I had never run into anything like them before. Over the last few days I’ve played around with them to the point where I feel mostly comfortable using them and at least have a basic understanding of why they exist. So let’s take a look at what they have to offer.

What are enums?

Enum is short for enumeration. It’s a fancy way of saying a set of constants that you wish to group together. Common examples for this would be days of the week or a deck of cards. Both of these have a set number of items in them that wouldn’t change and would be better grouped together.

Here’s a super basic example of what an enum class might look like, using the months of the year:

public enum Month {
   January, February, March, April, May, June, July, August, September, October, November, December;
}

That’s all that’s required to declare an enum. Notice the enum keyword between public and the name of the enum. This is what defines the object as being an enum vs a normal class.

When you create the enum, you’re defining both the new type (enum class) as well as the values that it’s allowed to have. This is very handy because it can be used to restrict what people are able to pass into a method by making its parameter an instance of your enum object.

This is not to say that you couldn’t have a constructor and methods. In fact we’ll actually take a look at an example that does that shortly.

When defining a new enum, note that the enum data type already implicitly extends the Enum class. Which means that you cannot extend another class from your enum class. You can, however, implement interfaces just fine.

Basic Enum Examples

Let’s look at some basic examples of how you could use the above Month enum in practice.

If/Else Checks

It’s possible to do a direct comparison between an instance of an enum object and an enum value using the == comparison. As shown below, this code will check the received Month against each of the Months in enum and return the matching month number:

public class MonthHandler {

   public int enumInIfStatement(Month month) {
       if(month == Month.January) {
           return 1;
       }else if(month == Month.February) {
           return 2;
       }else if(month == Month.March) {
           return 3;
       }else if(month == Month.April) {
           return 4;
       }else if(month == Month.May) {
           return 5;
       }else if(month == Month.June) {
           return 6;
       }else if(month == Month.July) {
           return 7;
       }else if(month == Month.August) {
           return 8;
       }else if(month == Month.September) {
           return 9;
       }else if(month == Month.October) {
           return 10;
       }else if(month == Month.November) {
           return 11;
       }else if(month == Month.December) {
           return 12;
       } else {
           throw new IllegalArgumentException("Month not supported");
       }
   }
}

An example usage test would look like:

@Test
public void checkMonthOctoberTest() {

   MonthHandler monthHandler = new MonthHandler();

   int result = monthHandler.enumInIfStatement(Month.October);

   Assert.assertEquals(10, result);
}

Case Statement

We could do the exact same thing we did above a lot cleaner with a case statement, keying off of the passed in month:

   public int enumInSwitchStatement(Month month) {
       switch (month) {
           case January: return 1;
           case February: return 2;
           case March: return 3;
           case April: return 4;
           case May: return 5;
           case June: return 6;
           case July: return 7;
           case August: return 8;
           case September: return 9;
           case October: return 10;
           case November: return 11;
           case December: return 12;
           default: throw new IllegalArgumentException("This isn't right");
       }
   }

Notice how we don’t have to make an explicit call do grab the value from the object, we just need to put the value.

The test case would be exactly the same as we did for our if/else:

   @Test
   public void checkMonthInSwitchStatementOctoberTest() {

       MonthHandler monthHandler = new MonthHandler();

       int result = monthHandler.enumInSwitchStatement(Month.October);

       Assert.assertEquals(10, result);
   }

Iterating over enums

Enums come with a few different extra methods without needing to implement them. One of these methods is the values() method. This will, intuitively, give you all of the enum values. Using our Month enum from before, we can use the values() method in combination with a for each loop to iterate through the items:

   @Test
   public void enumValuesTest() {
       for(Month month: Month.values()) {
           System.out.println(month);
       }
   }

Alternatively, we could do something more complex to check to see if an incoming variable belongs to the enum set:

   public boolean valueInEnum(String value) {
       Month month = Arrays.stream(Month.values()).filter(e -> e.name().equalsIgnoreCase(value)).findAny().orElse(null);
       return !(month == null);
   }

More Complex Example

The first example we looked at was the most basic. But as I mentioned before, it’s actually possible to include constructors and methods within an enumeration.

Let’s take a look at an example I’ve been using during one of my other courses:

public enum CoffeeType {
   Espresso(7, 0),
   Latte(7, 227),
   FilterCoffee(10,0);

   private int requiredBeans;
   private int requiredMilk;

   CoffeeType(int requiredBeans, int requiredMilk) {
       this.requiredBeans = requiredBeans;
       this.requiredMilk = requiredMilk;
   }

   public int getRequiredBeans() {
       return requiredBeans;
   }

   public int getRequiredMilk() {
       return requiredMilk;
   }
}

In the example above we see that each of the enum values are followed by a set of parentheses and values. This is a call to the constructor that is defined below it. We also have two getter methods present. This means that we could do something like Espresso.getRequiredBeans() within our code and get back the 7 that’s assigned to it.

Resources

For more reading on enums:

💚 A.B.L.