Wednesday, 31 May 2017

Tutorial 33: Enum



 In this tutorial, we are going to look at the Enum type in Java. 

Whenever you are writing programs, you will sometimes need to use certain variables that can only take on certain values. 

For example, let’s say we have a int variable called “month” that can only take up the months of the year. This is how the class would look like:

public class School {
            public static final int JANUARY = 1;
            public static final int FEBRUARY = 2;
            public static final int MARCH = 3;
            public static final int APRIL = 4;
            public static final int MAY = 5;
            public static final int JUNE = 6;
            public static final int JULY = 7;
            public static final int AUGUST = 8;
            public static final int SEPTEMBER = 9;
            public static final int OCTOBER = 10;
            public static final int NOVEMBER = 11;
            public static final int DECEMBER = 12;
            public static void main (String[] args) {
                        int month = MAY;
            }
}
Now, I can use a switch case construct like this:
public class School {
     public static final int JANUARY = 1;
     public static final int FEBRUARY = 2;
     public static final int MARCH = 3;
     public static final int APRIL = 4;
     public static final int MAY = 5;
     public static final int JUNE = 6;
     public static final int JULY = 7;
     public static final int AUGUST = 8;
     public static final int SEPTEMBER = 9;
     public static final int OCTOBER = 10;
     public static final int NOVEMBER = 11;
     public static final int DECEMBER = 12;

     public static void main(String[] args) {
           int month = MAY;

           switch (month) {
           case JANUARY:
                System.out.println("Month 1");
                break;
           case FEBRUARY:
                System.out.println("Month 2");
                break;
           case MARCH:
                System.out.println("Month 3");
                break;
           case APRIL:
                System.out.println("Month 4");
                break;
           case MAY:
                System.out.println("Month 5");
                break;
           case JUNE:
                System.out.println("Month 6");
                break;
           case JULY:
                System.out.println("Month 7");
                break;
           case AUGUST:
                System.out.println("Month 8");
                break;
           case SEPTEMBER:
                System.out.println("Month 9");
                break;
           case OCTOBER:
                System.out.println("Month 10");
                break;
           case NOVEMBER:
                System.out.println("Month 11");
                break;
           case DECEMBER:
                System.out.println("Month 12");
                break;
           }
     }
}

Figure 1 The problem that enum helps to fix

However, note that we can assign any value to int month. We might give it a value of 100. But what if we really just want it to refer to a certain set of values? What if you want to “lock” it such that it can only refer to a certain value set? Moreover, if you pass int month as an argument to other methods, you might not know that the constants defined in the class exist. So what we want is an object of a certain type that can be used to refer to members of a specific set.

This is why the Enum type exists. The word Enum stands for enumerated, which means counting through a list. So to create an Enum, go to File -> New -> Enum. In the dialog box that appears, give your Enum a name, in our case “Month” and click finish.

The Enum file looks like this:

public enum Month {
}

Now what we do is we write the list of the constant values separated by commas like this:

public enum Month {
            JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST,
                        SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER
}

Now, when you go back to the main class file, you can get rid of the constants that we declared earlier. Also, instead of saying int month, we can now create an object of type Enum like this:

public class School {
            public static void main (String[] args) {
                        Month month  = Month.MAY;
                        switch (month) {
                        }
            }
}
Now, a small warning sign will appear in Eclipse and most other IDEs and ask you whether it could fill in the rest of the switch statement. Click on the warning and go to “Add missing case statements” and Eclipse will generate the switch statement shown below.

Figure 2 Java fills up the switch automatically

This is mostly what you do with Enum types. Note that to refer to an enumerated type, you use the name of the Enum type followed by a dot, followed by the name of the value of the enum.

Figure 3 Switch statement that Java creates for you

More Advanced Uses of Enum
In the Enum file below:

public enum Month {
            JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST,
                        SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER
}

The items listed within the curly brackets are actually objects of the type of the name of the Enum file, which in this case is Month. 

To show you that this is the case, if we go to the main class, we can write the following and it will show that items listed in the enum file are indeed objects of the enum type.

System.out.println(Month.FEBRUARY.getClass());

will output “class Month”

The immediate parent of all enum types is Java.lang.enum. Everything that is in Java.lang is usually available in your programs and there is no need to use an import statement.

You can give the enum types you create a constructor and even methods. However, before you start creating methods and constructors, ensure that the list of enum objects ends with a semicolon. Enum constructors should be private or you can just leave off the access specifier, meaning it will have package-level access.

public enum Month {
            JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST,
                        SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER;

            Month () {
                        }
}

So, why would you need a constructor for your enum types even though we know that you cannot call “new” or declare the constructor “public”? The thing is, you can give the constructor a parameter or parameters. For example, in the above example, we could give every month an id as we create it like this:

 public enum Month {
            JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST,
                        SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER;

            Month (int id) {
                        }
}

Then, you supply the value of the parameter in round brackets in each object like this:

public enum Month {
JANUARY(1), FEBRUARY(2), MARCH(3), APRIL(4), MAY(5), JUNE(6), JULY(7), AUGUST(8),SEPTEMBER(9), OCTOBER(10), NOVEMBER(11), DECEMBER(12);

int id;

                        Month (int id) {
                                    this.id = id;
                        }
}

Now all the above isn’t of much use unless we have something we can use it with. So we can create a getter method to get the name of the objects like this:

public enum Month {
JANUARY(1), FEBRUARY(2), MARCH(3), APRIL(4), MAY(5), JUNE(6), JULY(7), AUGUST(8),SEPTEMBER(9), OCTOBER(10), NOVEMBER(11), DECEMBER(12);

int id;

                        Month (int id) {
                                    this.id = id;
                        }
                        public int getId() {
                        return id;
            }
}

Now in the main method, if we write:

System.out.println(Month.JULY.getId());

Java outputs 7 in the console.

You can even override the toString() method in your enum file like this:

public enum Month {
JANUARY(1), FEBRUARY(2), MARCH(3), APRIL(4), MAY(5), JUNE(6), JULY(7), AUGUST(8),SEPTEMBER(9), OCTOBER(10), NOVEMBER(11), DECEMBER(12);

int id;

                        Month (int id) {
                                    this.id = id;
                        }
                        public int getId() {
                                    return id;
                        }
                        public String toString(){
                                    return “The id of this month is: ” + id;
            }
}

If you use System.out.println on an object of the enum type, Java will call the toString() method and output the following: 

 Figure 4 An Enum looks neat
Now, what is we want to get the actual name i.e. the actual constant of the enumerated type. Notice that we have already overridden the toString() method. So to get the name of the constant, objects of Java.lang.enum have a method called name(), which returns the name constants of the enumerated types. Here is how to call the name() method:

System.out.println(Month.NOVEMBER.name());

Figure 5 The name() function in enum types

The name() method in enums is very important especially when you want to save enum constants in a database. You will normally want to get the name of the enum constant as a string before saving it to a database.

There is also a valueOf() method that is inherited from Java.lang.enum. What the valueOf() method does is the opposite of the name() method. So we can create a new instance of the enum type month and pass to it the name of an enum type like this:

Month month2 = Month.valueOf(“DECEMBER”);
System.out.println(month2);

Figure 6 The valueOf() function in enum types
That’s it for now on enums. If you have any questions or comments, please let me know by dropping them in the comments section below. I will make sure to answer them.

In the next tutorial, we are going to look at recursion.

Until then, take care.

No comments:

Post a Comment