EnumerationsS2C Home « Enumerations

In this lesson we go through enumerations which are also known as enumerated types or enums. Enumerations were introduced in Java5 and when you create an enum you're actually creating a new class that implicitly extends java.lang.Enum. We will talk more about extending classes in the OO Concepts section of the site in the Inheritance lesson. For now its enough to know that an enum can have constructors, variables and methods just like any other class and can be declared within its own class or as a member of another class. With enums you also get a constant-specific class body which we will investigate later in this lesson.

Basic Enumerationgo to top of page Top

In their simplest form enumerations are just a list of constants that define a new data type. Before Java5 the only way to do this would have been using static final variable to define Java constants. The difference between using enumerations and static final variables to define Java constants, is that with static final variable we can't guarantee that another piece of code won't set an invalid value, instead of using one of our static final variables. With enumerations, objects of the enumerated type can only hold values defined in the list of constants such as months of the year and days of the week for example. Lets look at some code to see this in action:


/*
  Enumeration of soups
*/ 
enum Soup {
    TOMATO, CHICKEN, PRAWN
}

Save and compile the file in directory   c:\_ObjectsAndClasses in the usual way. We create an enumeration using the enum keyword. The identifers TOMATO, CHICKEN and PRAWN are known as enumeration constants and are implicitly declared as public, static members of Soup. When we declare enumeration constants it's not obligatory to use all uppercase letters, but it lets others see this is a constant and we will use this convention here. Lets write a new test class for our Soup enum.


/*
  Test Class for Soup
*/ 
public class SoupTest {

    public static void main (String[] args) {
        Soup soup;  //  Here we create an enum variable of type Soup
        soup = Soup.PRAWN;  // We qualify our assigned enumeration constants
        System.out.println("Our soup is: " + soup);
    }
}

Save, compile and run the file in directory   c:\_ObjectsAndClasses in the usual way.

run Soup

The above screenshot shows the output of running our SoupTest class. We created a new Soup type object, notice how we didn't instantiate the object using the new keyword. In this regard declaring an enum is much the same as declaring a primitive type. The difference is that an object is automatically instantiated for each enumeration constant and this is what is used in assignment. We assign the enumeration constant, PRAWN, we defined in the Soup enumeration to our enum object and print it to the console. Notice how we qualify our assigned enumeration constants with the name of the enum, in our case Soup. Also what is not apparent is the fact that because our soup object is of type Soup, we can only assign values declared in the Soup enumeration or we get a compilation error.

Using Conditionals With Enumsgo to top of page Top

We can also use conditional branching via the if and switch constructs when using enums. Lets look at some code using an if construct by writing a new test class for our Soup enum.


/*
  Test Class2 for Soup
*/ 
public class SoupTest2 {

    public static void main (String[] args) {
        Soup soup = Soup.TOMATO;
        if (soup == Soup.CHICKEN) {
            System.out.println("Our " + soup + " soup has meat in it!");
        } else {
            System.out.println("Our " + soup + " soup has no meat in it!");
        }
    }
}

Save, compile and run the file in directory   c:\_ObjectsAndClasses in the usual way.

run Soup2

The above screenshot shows the output of running our SoupTest2 class. We created a new Soup type object and assigned the enumeration constant, TOMATO, we defined in Soup to our enum object. We then use an if construct to check our Soup value and output an appropriate message.

Using a switch construct with an enumeration works slightly differently:


/*
  Test Class3 for Soup
*/ 
public class SoupTest3 {

    public static void main (String[] args) {
        Soup soup = Soup.PRAWN;
        switch (soup) {
            case CHICKEN:
                System.out.println("Our " + soup + " soup has meat in it!");
                break;
            case PRAWN:
                System.out.println("Our " + soup + " soup has fish in it!");
                break;
            case TOMATO:
                System.out.println("Our " + soup + " soup has vegetables in it!");
                break;
        }
    }
}

Save, compile and run the file in directory   c:\_ObjectsAndClasses in the usual way.

run Soup3

The above screenshot shows the output of running our SoupTest3 class. We created a new Soup type object and assigned the enumeration constant, PRAWN, we defined in Soup to our enum object. We then use a switch construct to check our Soup value and output an appropriate message. A point to notice here is that the enumeration constants we are using for our case statements are not qualified by their enumeration type Soup. The enumeration type of Soup has already been implicitly applied within the switch statement itself and therefore is not required. Qualifying the case statements will actually cause a compilation error and so is something of a gotcha when using the switch construct with enumerations.

Enum Methodsgo to top of page Top

As mentioned earlier in the lesson enums are class types that extend java.lang.Enum and as such generally act like any other class type. Enumerations come with two predefined methods: values() which returns an array consisting of a list of enumeration constants and valueOf() which returns the enumeration constant corresponding to the passed string. Lets take a look at these methods using our Soup enumeration type:


/*
  Test Class4 for Soup
*/ 
public class SoupTest4 {

    public static void main (String[] args) {
        /*
          Using enum predefined values() method
        */ 
        Soup allSoups[] = Soup.values();
        for (Soup s : allSoups) {
            System.out.println("We have " + s + " soup in our list.");
        }
        /*
          Using enum predefined valueOf() method
        */ 
        Soup soup = Soup.valueOf("CHICKEN");
        System.out.println("Soup value is: " + soup);
    }
}

Save, compile and run the file in directory   c:\_ObjectsAndClasses in the usual way.

run Soup4

The above screenshot shows the output of running our SoupTest4 class. We create an array of the Soup enum constants using the predefined values() method and print then off using an enhanced for loop. We then use the predefined valueOf() method to extract the value of an enum constant.

Advanced Enumerationgo to top of page Top

So far we have only looked at basic enumerations, now it's time to examine some more advanced features of enumerations:


/*
  Enumeration of soups
*/ 
enum Soup {
    TOMATO("vegetable"), CHICKEN("meat"), PRAWN("seafood");
    String type;
    /*
      enum constructor
    */ 
    Soup(String type) {
        this.type = type;
    }
    /*
      get the 'type' instance variable
    */ 
    String getType() {
        return this.type;
    }
}

Save and compile the file in directory   c:\_ObjectsAndClasses in the usual way. Here we create an enumeration using the enum keyword but we give each of the enumeration constants TOMATO, CHICKEN and PRAWN a value. This means we need a constructor to instantiate this type and we also supply a method to get the value of the type instance variable. Let's write a new test class to test our enhanced Soup enum.


/*
  Test Class5 for Soup
*/ 
public class SoupTest5 {

    public static void main (String[] args) {
        for (Soup s : Soup.values()) {
            System.out.println("We have " + s + " soup in our list, which is a " 
                                          + s.getType() + " soup.");
        }
    }
}

Save, compile and run the file in directory   c:\_ObjectsAndClasses in the usual way.

run Soup5

The above screenshot shows the output of running our SoupTest5 class. We iterate through the Soup enum constants using the predefined values() method and an enhanced for loop. Within the loop we extract the type instance variable for each enum constant and print both off in a message.

Constant Specific Class Bodiesgo to top of page Top

We can also supply constant specific class bodies for our enums which are used to override methods within the enum class. We will expand our Soup enum to illustarte this:


/*
  Enumeration of soups
*/ 
enum Soup {
    TOMATO("vegetable") {  // Constant-specific class body 
        public String starRating() {  
            return "5 star rated"; 
        }
    },
    CHICKEN("meat"), 
    PRAWN("seafood") {  // Constant-specific class body  
        public String starRating() { 
            return "3 star rated"; 
        }
    };
    String type;
    /*
      enum constructor
    */ 
    Soup(String type) {
        this.type = type;
    }
    String getType() {
        return this.type;
    }
    /*
      default star rating
    */ 
    String starRating() {
        return "not rated yet";
    }
}

Save and compile the file in directory   c:\_ObjectsAndClasses in the usual way. Here we create an enumeration using the enum keyword but we give each of the enumeration constants TOMATO, CHICKEN and PRAWN a value. We also use some constant specific class bodies for our enums which we are using to override the starRating()method within the enum class. Lets write a new test class for our expanded enum.


/*
  Test Class6 for Soup
*/ 
public class SoupTest6 {

    public static void main (String[] args) {
        for (Soup s : Soup.values()) {
            System.out.println("We have " + s + " soup in our list, which is a " 
                                          + s.getType() + " soup and is " + s.starRating());
        }
    }
}

Save, compile and run the file in directory   c:\_ObjectsAndClasses in the usual way.

run Soup6

The above screenshot shows the output of running our SoupTest6 class. We iterate through the Soup enum constants using the predefined values() method and an enhanced for loop. Within the loop we extract the type instance variable for each enum constant and also get a star rating either from the constant specific class body or the default starRating() method if no constant specific class body exists as is the case for the CHICKEN enum constant.

Enum Singletonsgo to top of page Top

Singletons are classes that are instantiated exactly once and with the introduction of enumerated types in Java 5 we got a new way of making a singleton. We create an enum singleton with a single enumeration constant as follows:


/*
  Enumeration example of a singleton
*/ 
public enum ThereCanBeOnlyOne {
    INSTANCE
}

Save and compile the file in directory   c:\_ObjectsAndClasses in the usual way. Lets test our ThereCanBeOnlyOne enum singleton.


/*
  Test Class for ThereCanBeOnlyOne
*/ 
public class ThereCanBeOnlyOneTest {

    public static void main (String[] args) {
        ThereCanBeOnlyOne me = ThereCanBeOnlyOne.INSTANCE;
        System.out.println("Our instance " + me);
        ThereCanBeOnlyOne me2 = ThereCanBeOnlyOne.INSTANCE;
        System.out.println("Our instance " + me2);
    }
}

Save, compile and run the file in directory   c:\_ObjectsAndClasses in the usual way.

run singleton

The above screenshot shows the output of running our ThereCanBeOnlyOneTest class. We are not creating two instances of the ThereCanBeOnlyOneTest class, just returning the same enum singleton each time into named variables. This is because enumeration constants are implicitly declared as public, static members of the enumerated class, so by having just a single element enum type we are ensuring that only one instance is ever created.

Lesson 8 Complete

In this lesson we studied enumerations which were introduced in Java5.

What's Next?

Up until now we haven't really worried about our data and how we expose it to the outside world. That is all about to change as we look at encapsulation.

go to home page Homepage go to top of page Top