Enums
An enum (which is short for “enumeration”) is a Java data type used to define a fixed set of constants. Java enums are a special kind of Java class that defines the possible values a variable can have. For example, if we created an enum type called Direction with values NORTH, SOUTH, EAST, and WEST, we are saying that any variable of type Direction can only ever have one of those four values.
Day of Week Example
In the Java programming language, you define an enum type by using the enum
keyword. For example, you would specify a days-of-the-week enum type as:
public enum DayOfWeek {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY;
}
Below we show you examples of valid and invalid DayOfWeek
variable assignments.
// Valid examples
DayOfWeek day1 = DayOfWeek.MONDAY;
DayOfWeek day2 = DayOfWeek.TUESDAY;
DayOfWeek day3 = DayOfWeek.WEDNESDAY;
DayOfWeek day4 = DayOfWeek.THURSDAY;
DayOfWeek day5 = DayOfWeek.FRIDAY;
DayOfWeek day6 = DayOfWeek.SATURDAY;
DayOfWeek day7 = DayOfWeek.SUNDAY;
// Invalid examples
DayOfWeek day8 = DayOfWeek.Friday; // the name must match exactly - FRIDAY instead
DayOfWeek day9 = DayOfWeek.SABADO; // this is not in our list of constants
Here is some code that shows you how to use the DayOfWeek
enum defined above:
public class EnumTest {
public void tellMeIfItsTheWeekend(DayOfWeek day) {
if(day == DayOfWeek.SATURDAY || day == DayOfWeek.SUNDAY) {
System.out.println("Wooo! It's the weekend!");
} else if(day == DayOfWeek.FRIDAY) {
System.out.println("So close! Only 1 more day until the weekend!");
} else {
System.out.println("Hang in there! Not the weekend yet!");
}
}
public void testTellMeIfItsTheWeekend() {
DayOfWeek thirdDay = DayOfWeek.WEDNESDAY;
tellMeIfItsTheWeekend(thirdDay);
DayOfWeek fifthDay = DayOfWeek.FRIDAY;
tellMeIfItsTheWeekend(fifthDay);
DayOfWeek seventhDay = DayOfWeek.SUNDAY;
tellMeIfItsTheWeekend(seventhDay);
}
}
The output from running testTellMeIfItsTheWeekend()
is:
Hang in there! Not the weekend yet!
So close! Only 1 more day until the weekend!
Wooo! It's the weekend!
toString()
Method
What if we wanted to print out which day we were passing to the method before calling it? We probably would try something like this:
System.out.println(thirdDay);
This would print out: ‘WEDNESDAY’. Previously we learned that if you didn’t write your own toString()
method the memory location of your object would print out, but since enums are a special kind of class they get a special kind of toString()
. By default, calling the toString()
method on an enum variable will print out its name, in all caps, just like we defined it. This is the same behavior as any enum’s name()
method, a method we get for free because we are a special class. (Jeez - enums must be Java’s favorite child!) The name method also returns the name of the enum constant, exactly as declared in its enum declaration. What if we don’t want the all-caps version of our constant, but instead a more friendly version like ‘Wednesday’. Of course, we can still write a custom toString()
method, and that handy name()
method can help us. See the toString()
method we have added to the DayOfWeek
enum below:
public enum DayOfWeek {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY;
// prints days starting with a capital letter, followed by lowercase letters
// Ex: MONDAY -> Monday
@Override
public String toString() {
return name().substring(0, 1) + name().substring(1).toLowerCase();
}
}
Below is an updated version of our testTellMeIfItsTheWeekend()
method.
public void testTellMeIfItsTheWeekend() {
DayOfWeek thirdDay = DayOfWeek.WEDNESDAY;
System.out.println("Today is: " + thirdDay);
System.out.print("Is it the weekend? ");
tellMeIfItsTheWeekend(thirdDay);
System.out.println();
DayOfWeek fifthDay = DayOfWeek.FRIDAY;
System.out.println("Today is: " + fifthDay);
System.out.print("Is it the weekend? ");
tellMeIfItsTheWeekend(fifthDay);
System.out.println();
DayOfWeek seventhDay = DayOfWeek.SUNDAY;
System.out.println("Today is: " + seventhDay);
System.out.print("Is it the weekend? ");
tellMeIfItsTheWeekend(seventhDay);
}
The output from running testTellMeIfItsTheWeekend()
is now:
Today is: Wednesday
Is it the weekend? Hang in there! Not the weekend yet!
Today is: Friday
Is it the weekend? So close! Only 1 more day until the weekend!
Today is: Sunday
Is it the weekend? Wooo! It's the weekend!
Methods and Fields in an Enum
Above we defined a method in the enum definition. We can also add fields and even more methods. Let’s write a method called “plus” that accepts an integer and adds that many days to the enum, then returns the new day.
Example Usage:
DayOfWeek day1 = DayOfWeek.MONDAY;
DayOfWeek sevenDaysLater = day1.plus(7);
System.out.println(sevenDaysLater); //prints Monday
DayOfWeek seventeenDaysLater = day1.plus(17);
System.out.println(seventeenDaysLater); //prints Thursday
Thinking about how to do this, it would help if we had an integer value for each day that we could use for the addition of days. Let’s update our DayOfWeek
enum to keep an int field called ordering. We will also add a constructor that allows this value to be set.
public enum DayOfWeek {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY;
private int ordering;
private DayOfWeek(int ordering) {
this.ordering = ordering;
}
@Override
public String toString() {
return name().substring(0, 1) + name().substring(1).toLowerCase();
}
}
Note: our constructor has private visibility. Enums that define a constructor cannot make it public. Remember, the whole point of an enum is to have a fixed set of constants. A public constructor would allow anyone to create new values; a day of the week called ‘SABADO’ could get inserted. We will keep the ordering field private as well. This value should remain constant as well.
The above code doesn’t compile yet. Now that we have defined a constructor we have to use it to create our set of constants. We’ll start counting at 0, as all good computer scientists do. See the updated version below:
public enum DayOfWeek {
MONDAY(0),
TUESDAY(1),
WEDNESDAY(2),
THURSDAY(3),
FRIDAY(4),
SATURDAY(5),
SUNDAY(6);
private int ordering;
private DayOfWeek(int ordering) {
this.ordering = ordering;
}
@Override
public String toString() {
return name().substring(0, 1) + name().substring(1).toLowerCase();
}
}
Next let’s implement our plus function. We want to take the current ordering value, add to it the number of days the caller wants to move forward, and then we want to do something that will yield a new day’s ordering value. This is a pretty similar problem to your shift in the Caesar Cipher from Course 3. If you shifted ‘y’ by 6 you wanted to end up with ‘e’, wrapping it past ‘z’ and around to the beginning of the alphabet. So if we want to shift ‘THURSDAY’ by 6 we want to end up with ‘WEDNESDAY’. We can see this by repeating the days of week and counting off by 6. We wrap past Sunday and back to Wednesday.
▼ | ▼ | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
MON | TUE | WED | THU | FRI | SAT | SUN | MON | TUE | WED | THU | FRI | SAT | SUN |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
What if we want to shift by 10 (add 10 days)? ‘THURSDAY’ + 10 = ‘SUNDAY’
▼ | ▼ | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
MON | TUE | WED | THU | FRI | SAT | SUN | MON | TUE | WED | THU | FRI | SAT | SUN |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
We want to calculate ‘THURSDAY’ + 6, and THURSDAY has the ordering value of 3. So, 3 + 6 gives us 9. We learned in the Caesar Cipher problem that we can get back to our ordering values by using the modulo operator. We want to take the result and mod it by the number of unique values we have, 7. This would give us 2, and 2 is the ordering value of ‘WEDNESDAY’.
'THURSDAY' + 6
3 + 6 = 9
9 % 7 = 2
2 = WEDNESDAY
Take a look at the code for the plus method below:
public enum DayOfWeek {
MONDAY(0),
TUESDAY(1),
WEDNESDAY(2),
THURSDAY(3),
FRIDAY(4),
SATURDAY(5),
SUNDAY(6);
private int ordering;
private DayOfWeek(int ordering) {
this.ordering = ordering;
}
public DayOfWeek plus(int numberOfDays) {
if(numberOfDays < 0) {
throw new IllegalArgumentException("Number of days must be positive.");
}
int newOrderingValue = (this.ordering + numberOfDays) % 7;
for (DayOfWeek day : DayOfWeek.values()) { // we describe the values method be
if (day.ordering == newOrderingValue) {
return day;
}
}
// If we got here someone has broken the DayOfWeek enum. We no longer have 7 v
throw new IllegalStateException("Could not find a day for ordering value: "
+ newOrderingValue);
}
@Override
public String toString() {
return name().substring(0, 1) + name().substring(1).toLowerCase();
}
}
Suit Example
Below is another example of an enum, representing the suit from a standard deck of cards.
public enum Suit {
CLUBS("black"),
DIAMONDS("red"),
HEARTS("red"),
SPADES("black");
private String color;
private Suit(String suitColor) {
this.color = suitColor;
}
public String getColor() {
return this.color;
}
public boolean isBlack() {
return "black".equals(this.color);
}
public boolean isRed() {
return "red".equals(this.color);
}
}
values()
Method
The compiler automatically adds some special methods when it creates an enum. For example, all enums have a values
method that returns an array containing all of the values of the enum in the order they are declared. This method is commonly used in combination with the for-each construct to iterate over the values of an enum type. For example:
for (Suit suit : Suit.values()) {
String output = String.format("The suit: %s is the color %s.%n", suit, suit.getColor());
System.out.println(output);
}
This code prints out:
The suit: CLUBS is the color black.
The suit: DIAMONDS is the color red.
The suit: HEARTS is the color red.
The suit: SPADES is the color black.