Pages

How to use the Enum class

Hi! Imagine that you've been given the following task: create a class that implements the days of the week. How to use the Enum class - 1At first glance, this seems rather straightforward. Your code would look something like this:
public class DayOfWeek {

   private String title;

   public DayOfWeek(String title) {
       this.title = title;
   }

   public static void main(String[] args) {
       DayOfWeek dayOfWeek = new DayOfWeek("Saturday");
       System.out.println(dayOfWeek);
   }

   @Override
   public String toString() {
       return "DayOfWeek{" +
               "title='" + title + '\'' +
               '}';
   }
}
Everything seems to be fine, but there is one problem: you can pass any text to the constructor of the DayOfWeek class. That means someone could create a day of the week named "Frog", "Cloud" or "azaza322". This is clearly not the behavior that we expect, since there are only 7 real days of the week, and each of them has a specific name. Therefore, our task is to somehow limit the range of possible values for the DayOfWeek class. Before Java 1.5 came along, developers had to independently invent their own solutions to this problem, since the language didn't have a ready-made solution. In those days, if programmers needed to limit the number of values, they did this:
public class DayOfWeek {

   private String title;

   private DayOfWeek(String title) {
       this.title = title;
   }

   public static DayOfWeek SUNDAY = new DayOfWeek("Sunday");
   public static DayOfWeek MONDAY = new DayOfWeek("Monday");
   public static DayOfWeek TUESDAY = new DayOfWeek("Tuesday");
   public static DayOfWeek WEDNESDAY = new DayOfWeek("Wednesday");
   public static DayOfWeek THURSDAY = new DayOfWeek("Thursday");
   public static DayOfWeek FRIDAY = new DayOfWeek("Friday");
   public static DayOfWeek SATURDAY = new DayOfWeek("Saturday");

   @Override
   public String toString() {
       return "DayOfWeek{" +
               "title='" + title + '\'' +
               '}';
   }
}
Here's what you should notice:
  • The constructor is private. If a constructor is marked with the private modifier, it cannot be used to create an object. And since the class has only one constructor, no DayOfWeek objects can ever be created.
    public class Main {
    
         public static void main(String[] args) {
    
              DayOfWeek sunday = new DayOfWeek(); // Error!
         }
    }

  • Of course, the class does have the required number of public static objects, which were correctly initialized (using the correct names of the days of the week).
    This allowed these objects to be used in other classes.
    public class Person {
    
         public static void main(String[] args) {
    
              DayOfWeek sunday = DayOfWeek.SUNDAY;
    
              System.out.println(sunday);
         }
    }
    Output:
    DayOfWeek{title = 'Sunday'}
This approach largely solves the problem. We have 7 days of the week at our disposal, and nobody can create new ones. This solution was offered by Joshua Bloch in his book Effective Java. By the way, that book is very cool and a must-read for any Java developer. How to use the Enum class - 2With the release of Java 1.5, the language gained a ready-made solution for such situations: Enum. Enum is also a class. It is specially "fine-tuned" to solving problems like this, i.e. creating a certain limited range of values. Java's creators already had ready examples (for example, C already had enum), so they were able to create the best variant. So what is Enum in Java? Let's revisit our DayOfWeek example:
public enum DayOfWeek {

   SUNDAY,
   MONDAY,
   TUESDAY,
   WEDNESDAY,
   THURSDAY,
   FRIDAY,
   SATURDAY
}
Now that looks a lot simpler :) Internally, our Enum has 7 static constants. And that's something we can use it to implement a program. For example, let's write a program that determines whether a student needs to go to school today. Our student will have a daily schedule, represented by the StudentSchedule class:
public class StudentSchedule {

   private DayOfWeek dayOfWeek;
   // ... other fields


   public DayOfWeek getDayOfWeek() {
       return dayOfWeek;
   }

   public void setDayOfWeek(DayOfWeek dayOfWeek) {
       this.dayOfWeek = dayOfWeek;
   }
}
The schedule object's dayOfWeek variable determines which day is today. And here's our student class:
public class Student {

   private StudentSchedule schedule;
   private boolean goToSchool;

   public void wakeUp() {

       if (this.schedule.getDayOfWeek() == DayOfWeek.SUNDAY) {
           System.out.println("Hooray, you can sleep more!");
       } else {
           System.out.println("Damn, time for school again :(");
       }
   }
}
In the wakeUp() method, we use Enum to determine what the student should do next. We didn't even provide details about each field in DayOfWeek, and we don't need to: it's obvious how the days of the week are supposed to work. If we use it in its current form, any developer would understand what is happening in our code. Another example of the convenience of Enum is that its constants can be used with the switch statement. For example, let's write a program for a strict diet, in which dishes are scheduled by day:
public class VeryStrictDiet {

   public void takeLunch(DayOfWeek dayOfWeek) {

       switch (dayOfWeek) {

           case SUNDAY:
               System.out.println("Sunday Dinner! You can even enjoy something a little sweet today.");
           case MONDAY:
               System.out.println("Lunch for Monday: chicken noodle soup!");
           case TUESDAY:
               System.out.println("Tuesday, today it's celery soup :(");
               // ... and so on to the end
       }
   }
}
This is one of Enum's advantages over the old solution used before Java 1.5 — the old solution could not be used with switch. What else do you need to know about Enum? Enum is a real class with all the possibilities that this entails. For example, if the current implementation of the days of the week is inadequate, you can add variables, constructors, and methods to DayOfWeek:
public enum DayOfWeek {

   SUNDAY ("Sunday"),
   MONDAY ("Monday"),
   TUESDAY ("Tuesday"),
   WEDNESDAY ("Wednesday"),
   THURSDAY ("Thursday"),
   FRIDAY ("Friday"),
   SATURDAY ("Saturday");

   private String title;

   DayOfWeek(String title) {
       this.title = title;
   }

   public String getTitle() {
       return title;
   }

   @Override
   public String toString() {
       return "DayOfWeek{" +
               "title='" + title + '\'' +
               '}';
   }
}
Now our Enum constants have a title field, getter, and overridden toString method. Compared to regular classes, one serious limitation was placed on Enum — it cannot be inherited. Additionally, enumerations have characteristic methods:
  • values(): returns an array of all the values in the Enum:
    public static void main(String[] args) {
         System.out.println(Arrays.toString(DayOfWeek.values()));
    }
    Output:
    [DayOfWeek{title = 'Sunday'}, DayOfWeek{title = 'Monday'}, DayOfWeek{title = 'Tuesday'}, DayOfWeek{title = 'Wednesday'}, DayOfWeek{title = 'Thursday'}, DayOfWeek{title = 'Friday'}, DayOfWeek{title = 'Saturday'}]
  • ordinal(): returns the ordinal number of the constant. The numbering starts from zero:
    public static void main(String[] args) {
    
         int sundayIndex = DayOfWeek.SUNDAY.ordinal();
         System.out.println(sundayIndex);
    }
    Output:
    0
  • valueOf(): returns the Enum object that corresponds to the passed name:
    public static void main(String[] args) {
       DayOfWeek sunday = DayOfWeek.valueOf("SUNDAY");
       System.out.println(sunday);
    }
    Output:
    DayOfWeek{title = 'Sunday'}
Note: we use uppercase letters to specify Enum fields. These are constants so they use all-caps rather than camelCase.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.