Working with Enums Flashcards
Working with Enums
- An enumeration, or enum for short, is like a fixed set of constants.
- Using an enum is much better than using a bunch of constants because it provides typesafe checking.
- With numeric or String constants, you can pass an invalid value and not find out until runtime.
- With enums, it is impossible to create an invalid enum value without introducing a compiler error.
- Enumerations show up whenever you have a set of items whose types are known at compile time.
Creating Simple Enums
To create an enum, declare a type with the enum keyword, a name, and a list of values, as shown below:
// public or package access // keyword: enum // name of enum: Season public enum Season { WINTER, SPRING, SUMMER, FALL; // enum values (comma separated) // Semicolon optional for simple enums }
the semicolon at the end of the list is optional.
> [!NOTE]
Enum values are considered constants and are commonly written using snake case.
For example, an enum declaring a list of ice cream flavors might include values like VANILLA, ROCKY_ROAD, MINT_CHOCOLATE_CHIP
, and so on.
Using an enum
var s = Season.SUMMER; System.out.println(Season.SUMMER); // SUMMER System.out.println(s == Season.SUMMER); // true
- As you can see, enums print the name of the enum when toString() is called.
- They can be compared using == because they are like static final constants.
- In other words, you can use equals() or == to compare enums, since each enum value is initialized only once in the Java Virtual Machine (JVM).
Cannot extends enum
public enum ExtendedSeason extends Season {} // DOES NOT COMPILE
Calling the values(), name(), and ordinal() Methods
An enum provides a values() method to get an array of all of the values.
You can use this like any normal array, including in a for-each loop:
for (var season: Season.values()) { System.out.println(season.name() + " " + season.ordinal()); }
Output:
~~~
WINTER 0
SPRING 1
SUMMER 2
FALL 3
~~~
if ( Season.SUMMER == 2) {} // DOES NOT COMPILE
You can’t compare an int and an enum value directly anyway since an enum is a type, like a Java class, and not a primitive int.
Calling the valueOf () Method
Another useful feature is retrieving an enum value from a String using the valueOf() method. This is helpful when working with older code or parsing user input. The String passed in must match the enum value exactly, though.
Season s = Season.valueOf("SUMMER"); // SUMMER Season t = Season.valueOf("summer"); // IllegalArgumentException
Using Enums in switch Statements
Enums can be used in switch statements and expressions.
Season summer = Season.SUMMER; switch(summer) { case WINTER: System.out.print("Get out the sled!"); break; case SUMMER: System.out.print("Time for the pool!"); break; default: System.out.print("Is it summer yet?"); }
we just typed the value of the enum rather than writing Season.WINTER. After all, the compiler already knows that the only possible matches can be enum values. Java treats the enum type as implicit. In fact, if you were to type case Season.WINTER, it would not compile.
Season summer = Season.SUMMER; var message = switch(summer) { case Season.WINTER -> "Get out the sled!"; // DOES NOT COMPILE case 0 -> "Time for the pool!"; // DOES NOT COMPILE default -> "Is it summer yet?"; }; System.out.print(message);
Adding Constructors, Fields, and Methods
1: public enum Season { 2: WINTER("Low"), SPRING("Medium"), SUMMER("High"), FALL("Medium"); 3: private final String expectedVisitors; 4: private Season(String expectedVisitors) { 5: this.expectedVisitors = expectedVisitors; 6: } 7: public void printExpectedVisitors() { 8: System.out.println(expectedVisitors); 9: } 10: }
There are a few things to notice here.
* On line 2, the list of enum values ends with a semicolon (;). While this is optional when our enum is composed solely of a list of values, it is required if there is anything in the enum besides the values.
* Lines 3–9 are regular Java code. We have an instance variable, a constructor, and a method. We mark the instance variable private and final on line 3 so that our enum properties cannot be modified.
* All enum constructors are implicitly private, with the modifier being optional. This is reasonable since you can’t extend an enum and the constructors can be called only within the enum itself. In fact, an enum constructor will not compile if it contains a public or protected modifier.
What about the parentheses on line 2? Those are constructor calls, but without the new keyword normally used for objects. The first time we ask for any of the enum values, Java constructs all of the enum values. After that, Java just returns the already constructed enum values.
Although it is possible to create an enum with instance variables that can be modified, it is a very poor practice to do so since they are shared within the JVM. When designing an enum, the values should be immutable.
public enum OnlyOne { ONCE(true); private OnlyOne(boolean b) { System.out.print("constructing,"); } } public class PrintTheOne { public static void main(String[] args) { System.out.print("begin,"); OnlyOne firstCall = OnlyOne.ONCE; // Prints constructing, OnlyOne secondCall = OnlyOne.ONCE; // Doesn't print anything System.out.print("end"); } }
Output :
begin,constructing,end
If the OnlyOne enum was used earlier in the program, and therefore initialized sooner, then the line that declares the firstCall variable would not print anything.
How do we call an enum method?
That’s easy, too: we just use the enum value followed by the method call.
Season.SUMMER.printExpectedVisitors();
public enum Season { WINTER { public String getHours() { return "10am-3pm"; } }, SPRING { public String getHours() { return "9am-5pm"; } }, SUMMER { public String getHours() { return "9am-7pm"; } }, FALL { public String getHours() { return "9am-5pm"; } }; public abstract String getHours(); }
If we forget to implement the method for one of the values, we get a compiler error:
The enum constant WINTER must implement the abstract method getHours()
What if we don’t want each and every enum value to have a method?
We can create an implementation for all values and override it only for the special cases.
public enum Season { WINTER { public String getHours() { return "10am-3pm"; } }, SUMMER { public String getHours() { return "9am-7pm"; } }, SPRING, FALL; public String getHours() { return "9am-5pm"; } }
We only code the special cases and let the others use the enum-provided implementation.