Skip to content

Enumerations

Java enums (declared using the enum keyword) are shorthand syntax for sizable quantities of constants of a single class. Enumerated values are used to represent a set of named values. Historically in Java (and other languages), these were often stored as constants. For example:

``` public static final int SEASON_SPRING = 0; public static final int SEASON_SUMMER = 1; public static final int SEASON_FALL = 2; public static final int SEASON_WINTER = 3;

There are, however, a number of issues with this approach:
* Acceptable values are not obvious
    * Since the values are just integers, it’s hard at a glance to tell what the possible values are.
* No type safety
    * Since the values are just integers, the compiler will let you substitute any valid integer.
* No name-spacing
    * With our seasone example, we prefixed each of the suits with “SEASON_”
    * We chose to prefix all of those constants with this prefix to potentially disambiguate from other enumerated values of the same class
* Not printable
    * Since they are just integers, if we were to print out the values, they’d simply display their numerical value


##  basic enum

Enum can be considered to be syntax sugar for a sealed class that is instantiated only a number of times known at compile-time to define a set of constants. A simple enum to list the different seasons would be declared as follows:
public enum Season {
WINTER,
SPRING,
SUMMER,
FALL }
While the enum constants don't necessarily need to be in all-caps, it is Java convention that names of constants are entirely uppercase, with words separated by underscores.

You can declare an Enum in its own file (the following enum is declared in the Season.java file) :
/* * This enum is declared in the Season.java file. / public enum Season {
WINTER,
SPRING,
SUMMER,
FALL }
## Usage

We can declare the enum alone or inside another class. we cannot declare an Enum inside a method body or constructor.
Every constant of enum is **public**, **static** and **final** by default. As every constant is static, they can be accessed directly using the enum name.

Enum constants can be passed around as method parameters:
public static void display(Season s) {
// name() is a built-in method that gets the exact name of the enum constant System.out.println(s.name());
} display(Season.WINTER); // Prints out "WINTER"
You can get an array of the enum constants using the `values()` method. The values are guaranteed to be in declaration order in the returned array. It is important to note however that this method returns a new array every time it is called: 
Season[] seasons = Season.values();
You can use this method to iterate over the values. 
public static void enumIterate() {
for (Season s : Season.values()) {
System.out.println(s.name());
} }
You can use enums in a switch statement:
public static void enumSwitchExample(Season s) {
switch(s) {
case WINTER:
System.out.println("It's pretty cold");
break;
case SPRING:
System.out.println("It's warming up");
break;
case SUMMER:
System.out.println("It's pretty hot");
break;
case FALL:
System.out.println("It's cooling down");
break;
} }
You can also compare enum constants using `==:
Season.FALL == Season.WINTER // false Season.SPRING == Season.SPRING // true
Another way to compare enum constants is by using equals() as below, which is considered bad practice as you can easily fall into pitfalls as follows:
Season.FALL.equals(Season.FALL); // true Season.FALL.equals(Season.WINTER); // false Season.FALL.equals("FALL"); // false and no compiler error
##  Enums with Constructors

An enum cannot have a public constructor; however, private constructors are acceptable (constructors for enums are package-private by default):
public enum Coin {
PENNY(1), NICKEL(5), DIME(10), QUARTER(25); // usual names for US coins
// note that the above parentheses and the constructor arguments match
private int value;

Coin(int value) {
this.value = value;
} public int getValue() {
return value;
} } int p = Coin.NICKEL.getValue(); // the int value will be 5

It is recommended that you keep all fields private and provide getter methods, as there are a finite number of instances for an enum.
If you were to implement an Enum as a class instead, it would look like this:
public class Coin> implements Comparable, Serializable{
public static final Coin PENNY = new Coin(1);
public static final Coin NICKEL = new Coin(5);
public static final Coin DIME = new Coin(10);
public static final Coin QUARTER = new Coin(25); private int value; private Coin(int value){
this.value = value;
} public int getValue() {
return value;
} } int p = Coin.NICKEL.getValue(); // the int value will be 5
## Enums with Abstract Methods

Enums can define abstract methods, which each enum member is required to implement.
enum Action {
DODGE { public boolean execute(Player player) {
return player.isAttacking();
}
},
ATTACK {
public boolean execute(Player player) {
return player.hasWeapon();
}
},
JUMP {
public boolean execute(Player player) {
return player.getCoordinates().equals(new Coordinates(0, 0));
}
};

public abstract boolean execute(Player player); }

This allows for each enum member to define its own behaviour for a given operation, without having to switch on types in a method in the top-level definition.
Note that this pattern is a short form of what is typically achieved using polymorphism and/or implementing interfaces. 



## Implements Interface

This is an enum that is also a callable function that tests String inputs against precompiled regular expression patterns.
import java.util.function.Predicate; import java.util.regex.Pattern; enum RegEx implements Predicate { UPPER("[A-Z]+"), LOWER("[a-z]+"), NUMERIC("[+-]?[0-9]+"); private final Pattern pattern; private RegEx(final String pattern) { this.pattern = Pattern.compile(pattern); } @Override public boolean test(final String input) { return this.pattern.matcher(input).matches(); } } public class Main { public static void main(String[] args) { System.out.println(RegEx.UPPER.test("ABC")); System.out.println(RegEx.LOWER.test("abc")); System.out.println(RegEx.NUMERIC.test("+111")); } }
Each member of the enum can also implement the method:
import java.util.function.Predicate; enum Acceptor implements Predicate { NULL { @Override public boolean test(String s) { return s==null; } }, EMPTY { @Override public boolean test(String s) { return s.equals(""); } }, NULL_OR_EMPTY { @Override public boolean test(String s) { return NULL.test(s)||EMPTY.test(s); } }; } public class Main { public static void main(String[] args) {
System.out.println(Acceptor.NULL.test(null)); // true
System.out.println(Acceptor.EMPTY.test("")); // true
System.out.println(Acceptor.NULL_OR_EMPTY.test(" ")); // false
} }
## Implement Singleton with enum

Enum constants are instantiated when an enum is referenced for the first time. Therefore, that allows to implement Singleton software design pattern with a single-element enum.
public enum Attendant { INSTANCE; private Attendant() { // perform some initialization routine } public void sayHello() { System.out.println("Hello!"); } } public class Main { public static void main(String... args) { Attendant.INSTANCE.sayHello();// instantiated at this point } }
According to "Effective Java" book by Joshua Bloch, a single-element enum is the best way to implement a singleton. 

This approach has following advantages:
* thread safety 
* guarantee of single instantiation 
* out-of-the-box serialization

And as shown in the section implements interface this singleton might also implement one or more interfaces.



## Using methods and static blocks

An enum can contain a method, just like any class. To see how this works, we'll declare an enum like this:
public enum Direction { NORTH, SOUTH, EAST, WEST; }
Let's have a method that returns the enum in the opposite direction:
public enum Direction { NORTH, SOUTH, EAST, WEST; public Direction getOpposite(){
switch (this){
case NORTH:
return SOUTH;
case SOUTH:
return NORTH;
case WEST:
return EAST;
case EAST:
return WEST;
default: //This will never happen
return null; }
} }

This can be improved further through the use of fields and static initializer blocks:
public enum Direction { NORTH, SOUTH, EAST, WEST;

private Direction opposite;

public Direction getOpposite() { return opposite; }

static { NORTH.opposite = SOUTH; SOUTH.opposite = NORTH; WEST.opposite = EAST; EAST.opposite = WEST; } }

In this example, the opposite direction is stored in a private instance field opposite, which is statically initialized the first time a Direction is used. In this particular case (because `NORTH` references `SOUTH` and conversely), we cannot use Enums with constructors here (Constructors `NORTH(SOUTH)`, `SOUTH(NORTH)`, `EAST(WEST)`, `WEST(EAST)` would be more elegant and would allow opposite to be declared final, but would be self-referential and therefore are not allowed). 



## Zero instance enum

Just as enum can be used for singletons (1 instance classes), it can be used for utility classes (0 instance classes). Just make sure to terminate the (empty) list of enum constants with a ;.
enum Util {

/ No instances /;

public static int clamp(int min, int max, int i) {
return Math.min(Math.max(i, min), max);
}

// other utility methods... }

## Enum Polymorphism Pattern

When a method need to accept an "extensible" set of enum values, the programmer can apply polymorphism like on a normal class by creating an interface which will be used anywere where the enums shall be used:
public interface ExtensibleEnum {
String name(); }
This way, any enum tagged by (implementing) the interface can be used as a parameter, allowing the programmer to create a variable amount of enums that will be accepted by the method. This can be useful, for example, in APIs where there is a default (unmodifiable) enum and the user of these APIs want to "extend" the enum with more values.
A set of default enum values can be defined as follows:
public enum DefaultValues implements ExtensibleEnum {
VALUE_ONE, VALUE_TWO; }
Additional values can then be defined like this:
public enum ExtendedValues implements ExtensibleEnum {
VALUE_THREE, VALUE_FOUR; }
Sample which shows how to use the enums - note how printEnum() accepts values from both enum types:
private void printEnum(ExtensibleEnum val) {
System.out.println(val.name()); }
printEnum(DefaultValues.VALUE_ONE); // VALUE_ONE printEnum(DefaultValues.VALUE_TWO); // VALUE_TWO printEnum(ExtendedValues.VALUE_THREE); // VALUE_THREE printEnum(ExtendedValues.VALUE_FOUR); // VALUE_FOUR
This pattern does not prevent you from redefining enum values, which are already defined in one enum, in another enum. These enum values would be different instances then. Also, it is not possible to use switch-on-enum since all we have is the interface, not the real enum.


## EnumSet

To group, complement, range the enum values we have EnumSet class which contains different methods.

* **EnumSet#range** : To get subset of enum by range defined by two endpoints
* **EnumSet#of** : Set of specific enums without any range. Multiple overloaded of methods are there.
* **EnumSet#complementOf** : Set of enum which is complement of enum values provided in method parameter
enum Page { A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 }

public class Test { public static void main(String[] args) {

EnumSet<Page> range = EnumSet.range(Page.A1, Page.A5);
if (range.contains(Page.A4)) {
  System.out.println("Range contains A4");
}

EnumSet<Page> of = EnumSet.of(Page.A1, Page.A5, Page.A3);
if (of.contains(Page.A1)) {
  System.out.println("Of contains A1");
}

} } ```

Exercise

  • Exercise 1:

    • Create a public enum Weekday with constants for MONDAY, TUESDAY,... until SUNDAY.
      • The enum should have an instance method boolean isWeekDay() and an instance method boolean isHoliday().
      • The isHoliday() method should return the opposite of isWeekDay().
      • Write a program which demonstrates how this enum could be used, which has a method which takes a Weekday as the argument and prints a message depending on whether the Weekday is a holiday or not.
  • Exercise 2:

    • Use your weekday class to investigate if enums implement Comparable.
      • Declare a Weekday sat = Weekday.SATURDAY;.
      • Use a loop over Weekday.values() with day as loop variable and print out each value and whether it is less than, equal to or greater than sat, using the call day.compareTo(sat) - remember that the compareTo() method returns an int such that
        • a negative value means that day is less than sat
        • zero means that day is considered equal to sat (when comparing them on order)
        • a positive value means that day is greater than sat