Efficiently Managing Constants with Java Enums
Enum was introduced in Java 1.5 as a new type whose fields consist of a fixed set of constants. For example, we can create directions as Java Enum with fixed fields as EAST, WEST, NORTH, and SOUTH.
Java Enum
In this tutorial, we will learn how to create an Enum. We will also look into the benefits of using enums in Java and features of enum types. We will also learn using Java Enum valueOf, enum values, EnumSet, and EnumMap with examples.
Java Enum Example
Java enum keyword is used to create an enum type. Let’s have a look at the java enum example program.
package com.journaldev.enums;
public enum ThreadStates {
START,
RUNNING,
WAITING,
DEAD;
}
In the above example, ThreadStates is the enum with fixed constants fields START, RUNNING, WAITING, and DEAD.
Java Enum vs Constants
Now let’s see how java enum is better than normal constants fields in Java classes. Let’s create a similar constants class in java.
package com.journaldev.enums;
public class ThreadStatesConstant {
public static final int START = 1;
public static final int WAITING = 2;
public static final int RUNNING = 3;
public static final int DEAD = 4;
}
Now let’s see how both enum and constants are used in a java program:
/**
* This method shows the benefit of using Enum over Constants
*/
private static void benefitsOfEnumOverConstants() {
//Enum values are fixed
simpleEnumExample(ThreadStates.START);
simpleEnumExample(ThreadStates.WAITING);
simpleEnumExample(ThreadStates.RUNNING);
simpleEnumExample(ThreadStates.DEAD);
simpleEnumExample(null);
simpleConstantsExample(1);
simpleConstantsExample(2);
simpleConstantsExample(3);
simpleConstantsExample(4);
//we can pass any int constant
simpleConstantsExample(5);
}
private static void simpleEnumExample(ThreadStates th) {
if(th == ThreadStates.START) System.out.println("Thread started");
else if (th == ThreadStates.WAITING) System.out.println("Thread is waiting");
else if (th == ThreadStates.RUNNING) System.out.println("Thread is running");
else System.out.println("Thread is dead");
}
private static void simpleConstantsExample(int i) {
if(i == ThreadStatesConstant.START) System.out.println("Thread started");
else if (i == ThreadStatesConstant.WAITING) System.out.println("Thread is waiting");
else if (i == ThreadStatesConstant.RUNNING) System.out.println("Thread is running");
else System.out.println("Thread is dead");
}
If we look at the above example, we have two risks with using constants that are solved by the enum.
- We can pass any int constant to the simpleConstantsExample method but we can pass only fixed values to simpleEnumExample, so it provides type safety.
- We can change the int constants value in ThreadStatesConstant class but the above program will not throw any exception. Our program might not work as expected but if we change the enum constants, we will get compile time error that removes any possibility of runtime issues.
Java Enum Methods
Now let’s see more features of java enum with an example.
package com.journaldev.enums;
import java.io.Closeable;
import java.io.IOException;
/**
* This Enum example shows all the things we can do with Enum types
*
*/
public enum ThreadStatesEnum implements Closeable {
START(1) {
@Override
public String toString() {
return "START implementation. Priority=" + getPriority();
}
@Override
public String getDetail() {
return "START";
}
},
RUNNING(2) {
@Override
public String getDetail() {
return "RUNNING";
}
},
WAITING(3) {
@Override
public String getDetail() {
return "WAITING";
}
},
DEAD(4) {
@Override
public String getDetail() {
return "DEAD";
}
};
private int priority;
public abstract String getDetail();
// Enum constructors should always be private.
private ThreadStatesEnum(int i) {
priority = i;
}
// Enum can have methods
public int getPriority() {
return this.priority;
}
public void setPriority(int p) {
this.priority = p;
}
// Enum can override functions
@Override
public String toString() {
return "Default ThreadStatesConstructors implementation. Priority=" + getPriority();
}
@Override
public void close() throws IOException {
System.out.println("Close of Enum");
}
}
Java Enum Important Points
Below are some of the important points for Enums in Java.
- All java enum implicitly extends java.lang.Enum class that extends Object class and implements Serializable and Comparable interfaces. So we can’t extend any class in enum.
- Since enum is a keyword, we can’t end package name with it, for example com.journaldev.enum is not a valid package name.
- Enum can implement interfaces. As in above enum example, it’s implementing Closeable interface.
- Enum constructors are always private.
- We can’t create instance of enum using new operator.
- We can declare abstract methods in java enum, then all the enum fields must implement the abstract method. In above example getDetail() is the abstract method and all the enum fields have implemented it.
- We can define a method in enum and enum fields can override them too. For example, toString() method is defined in enum and enum field START has overridden it.
- Java enum fields has namespace, we can use enum field only with class name like ThreadStates.START.
- Enums can be used in switch statement, we will see it in action in the later part of this tutorial.
- We can extend existing enum without breaking any existing functionality. For example, we can add a new field NEW in ThreadStates enum without impacting any existing functionality.
- Since enum fields are constants, java best practice is to write them in block letters and underscore for spaces. For example EAST, WEST, EAST_DIRECTION etc.
- Enum constants are implicitly static and final.
- Enum constants are final but it’s variable can still be changed. For example, we can use setPriority() method to change the priority of enum constants. We will see it in usage in below example.
- Since enum constants are final, we can safely compare them using “==” and equals() methods. Both will have the same result.
Java EnumSet, EnumMap, valueOf()
Now we know most of the features of Enum, let’s have a look at Java Enum example program. Then we will learn some more features of an enum.
package com.journaldev.enums;
import java.io.IOException;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Set;
public class JavaEnumExamples {
public static void main(String[] args) throws IOException {
usingEnumMethods();
usingEnumValueOf();
usingEnumValues();
usingEnumInSwitch(ThreadStatesEnum.START);
usingEnumInSwitch(ThreadStatesEnum.DEAD);
usingEnumMap();
usingEnumSet();
}
private static void usingEnumSet() {
EnumSet enumSet = EnumSet.allOf(ThreadStatesEnum.class);
for(ThreadStatesEnum tsenum : enumSet) {
System.out.println("Using EnumSet, priority = " + tsenum.getPriority());
}
}
private static void usingEnumMap() {
EnumMap<ThreadStatesEnum, String> enumMap = new EnumMap<>(ThreadStatesEnum.class);
enumMap.put(ThreadStatesEnum.START, "Thread is started");
enumMap.put(ThreadStatesEnum.RUNNING, "Thread is running");
enumMap.put(ThreadStatesEnum.WAITING, "Thread is waiting");
enumMap.put(ThreadStatesEnum.DEAD, "Thread is dead");
Set keySet = enumMap.keySet();
for(ThreadStatesEnum key : keySet) {
System.out.println("key=" + key.toString() + ":: value=" + enumMap.get(key));
}
}
private static void usingEnumInSwitch(ThreadStatesEnum th) {
switch (th) {
case START:
System.out.println("START thread");
break;
case WAITING:
System.out.println("WAITING thread");
break;
case RUNNING:
System.out.println("RUNNING thread");
break;
case DEAD:
System.out.println("DEAD thread");
}
}
private static void usingEnumValues() {
ThreadStatesEnum[] thArray = ThreadStatesEnum.values();
for(ThreadStatesEnum th : thArray) {
System.out.println(th.toString() + "::priority=" + th.getPriority());
}
}
private static void usingEnumValueOf() {
ThreadStatesEnum th = Enum.valueOf(ThreadStatesEnum.class, "START");
System.out.println("th priority=" + th.getPriority());
}
private static void usingEnumMethods() throws IOException {
ThreadStatesEnum thc = ThreadStatesEnum.DEAD;
System.out.println("priority is:" + thc.getPriority());
thc = ThreadStatesEnum.DEAD;
System.out.println("Using overriden method." + thc.toString());
thc = ThreadStatesEnum.START;
System.out.println("Using overriden method." + thc.toString());
thc.setPriority(10);
System.out.println("Enum Constant variable changed priority value=" + thc.getPriority());
thc.close();
}
}