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
Enum constants are technically mutable, so a setter could be added to change the internal structure of an enum constant. However, this is considered very bad practice and should be avoided.
Related Article: Java Enums Tutorial with Examples
Best practice is to make Enum fields immutable, with final:
public enum Coin {
PENNY(1), NICKEL(5), DIME(10), QUARTER(25);
private final int value;
Coin(int value){
this.value = value;
}
…
}
You may define multiple constructors in the same enum. When you do, the arguments you pass in your enum declaration decide which constructor is called:
public enum Coin { PENNY(1, true), NICKEL(5, false), DIME(10), QUARTER(25); private final int value; private final boolean isCopperColored; Coin(int value){ this(value, false); } Coin(int value, boolean isCopperColored){ this.value = value; this.isCopperColored = isCopperColored; } … }
Note: All non-primitive enum fields should implement Serializable because the Enum class does.
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 pattern with a single element 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
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… }
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 ;.
See the question Zero instance enum vs private constructors for preventing instantiation for a discussion on pro’s and con’s compared to private constructors.
Enum as a bounded type parameter
When writing a class with generics in java, it is possible to ensure that the type parameter is an enum. Since all enums extend the Enum class, the following syntax may be used.
public class Holder> { public final T value; public Holder(T init) { this.value = init; } } In this example, the type T must be an enum.
Documenting enums
Not always the enum name is clear enough to be understood. To document an enum, use standard javadoc:
/** * United States coins * / public enum Coins { /** * One-cent coin, commonly known as a penny, * is a unit of currency equaling one-hundredth * of a United States dollar * / PENNY(1), /** * A nickel is a five-cent coin equaling * five-hundredth of a United States dollar * / NICKEL(5), /** * The dime is a ten-cent coin refers to * one tenth of a United States dollar * / DIME(10), /** * The quarter is a US coin worth 25 cents, * one-fourth of a United States dollar */ QUARTER(25); private int value; Coins(int value){ this.value = value; } public int getValue(){ return value; } }