Java Enum Tutorial
Java enum, also called Java enumeration type, is a type whose fields consist of a fixed set of constants. The very purpose of an enum is to enforce compile-time type safety. The enum keyword is one of the reserved keywords in Java.
We should use an enum when we know all possible values of a variable at compile time or design time, though we can add more values in the future as and when we identify them. In this java enum tutorial, we will learn what enums are and what problems they solve.
Enumerations (in general) are generally a set of related constants. They have been in other programming languages like C++ from the beginning. After JDK 1.4, Java designers decided to support it in Java also, and it was officially released in JDK 1.5 release.
The enumeration in Java is supported by keyword enum . The enums are a special type of class that always extends java.lang.Enum.
1.1. The enum is a Reserved Keyword
The enum is a reserved keyword which means we cannot define a variable with the name enum . e.g. It will result in compile time error «invalid VariableDeclaratorId» .
1.2. Syntax to Create Enums
As we know, generally we deal with four directions in daily life. Their names, angles and other properties are fixed. So, in programs, we can create an enum for them. The syntax to create an enum is as below:
Logically, each enum is an instance of enum type itself. So given enum can be seen as the below declaration. JVM internally adds ordinal and value methods to this class which we can call while working with an enum.
final class Direction extends Enum
By convention, enums are constants. In Java, constants are defined in all UPPER_CASE letters. This follows for enums also.
- Enum name should be in title case (same as class names).
- Enum fields should be in all UPPER CASE (same as static final constants).
We can create a variable of specified enum type just like we use final static class fields.
Direction north = Direction.NORTH; System.out.println(north); //Prints NORTH
By default, enums don’t require constructor definitions and their default values are always the string used in the declaration. Though, you can give define your own constructors to initialize the state of enum types.
For example, we can add angle attribute to direction. All directions have some angle.
enum Direction < EAST(0), WEST(180), NORTH(90), SOUTH(270); // constructor private Direction(final int angle) < this.angle = angle; >// internal state private int angle; public int getAngle() < return angle; >>
If we want to access the angle for any direction, we can make a simple method call in the enum field reference.
Direction west = Direction.WEST; System.out.println(west); System.out.println(west.getAngle()); //or System.out.println(Direction.WEST.getAngle());
By default, an enum will have the following methods to access its constants.
The ordinal() method returns the order of an enum instance among the list of constants. It represents the sequence in the enum declaration, where the initial constant is assigned an ordinal of ‘0’ . It is very much like array indices.
Ordinal is designed for use by sophisticated enum-based data structures, such as EnumSet and EnumMap .
Direction.EAST.ordinal(); //0 Direction.NORTH.ordinal(); //2
The enum values() method returns all the enum values as an enum array.
Direction[] directions = Direction.values(); for (Direction d : directions)
The enum valueOf() method helps to convert a string to an enum instance.
Direction east = Direction.valueOf("EAST"); System.out.println(east);
Remember that an enum is basically a special class type, and can have methods and fields just like any other class. We can add methods that are abstract as well as non-abstract methods. Both methods are allowed in the enum.
Adding a concrete method in an enum is similar to adding the same method in any other class. We can use any access specifier e.g. public , private or protected . We can return values from enum methods or simply use them to perform internal logic.
We can call the message() method as a simple method call on an enum instance.
We can also add abstract methods in enums. In this case, we must implement the abstract method at each enum field, individually.
public enum Direction < EAST < @Override public String message() < return "You are moving in east. You will face sun in morning time."; >>, WEST < @Override public String message() < return "You are moving in west. You will face sun in evening time."; >>, NORTH < @Override public String message() < return "You are moving in north. Sea behind."; >>, SOUTH < @Override public String message() < return "You are moving in south. Sea ahead."; >>; public abstract String message(); >
Direction.WEST.message(); //You are moving in west. You will face sun in evening time. Direction.NORTH.message(); //You are moving in north. Sea behind.
We can enforce a contract for all enums to be created in this way. It can serve as a template for enum creation.
For example, If we want that each enum type of Direction should be able to print the direction name with a custom message when needed. This can be done by defining a abstract method inside Direction , which each enum has to override.
As mentioned earlier, enum extends Enum class. The java.lang.Enum is an abstract class. This is the common base class of all Java enumeration types.
public abstract class Enum> extends Object implements Constable, Comparable, Serializable < //. >
It means that all enums are comparable and serializable implicitly. Also, all enum types in Java are singleton by default.
As noted all enums extends java.lang.Enum , so enum cannot extend any other class because Java does not support multiple inheritance this way. But enums can implement any number of interfaces.
All enums are by default comparable and singletons as well. It means you can compare them with equals() method, even with «= wp-block-code»> Direction east = Direction.EAST; Direction eastNew = Direction.valueOf(«EAST»); System.out.println( east == eastNew ); //true System.out.println( east.equals( eastNew ) ); //true
We can compare enum types using ‘==’ operator or equals() method, because enums are singlton and comparable by default.
Two classes have been added to java.util package in support of enums – EnumSet (a high-performance Set implementation for enums; all members of an enum set must be of the same enum type) and EnumMap (a high-performance Map implementation for use with enum keys).
EnumSet class is a specialized Set implementation for use with enum types. All of the elements in an enum set must come from a single enum type that is specified, explicitly or implicitly, when the set is created.
Set enumSet = EnumSet.of(Direction.EAST, Direction.WEST, Direction.NORTH, Direction.SOUTH );
Like most collection implementations EnumSet is not synchronized. If multiple threads access an enum set concurrently, and at least one of the threads modifies the set, it should be synchronized externally.
Note that null elements are not permitted in EnumSet. Also, these sets guarantee the ordering of the elements in the set based on their order in the enumeration constants is declared. Performance and memory benefits are very high in comparison to a regular set implementation.
EnumMap is a specialized Map implementation for use with enum type keys. Also, all of the keys in an enum map must come from a single enum type that is specified, explicitly or implicitly, when the map is created.
Like EnumSet , null keys are not permitted and is not synchronized as well.
Map enumMap = new EnumMap(Direction.class); enumMap.put(Direction.EAST, Direction.EAST.getAngle()); enumMap.put(Direction.WEST, Direction.WEST.getAngle()); enumMap.put(Direction.NORTH, Direction.NORTH.getAngle()); enumMap.put(Direction.SOUTH, Direction.SOUTH.getAngle());
In this article, we explored the Java enum from the language basics to more advanced and interesting real-world use cases.
Getting enum value by passing preset ordinal
I have looked this link : Convert from enum ordinal to enum type and tried to get the enum value. But is not working. My enum class is :
I will pass the values 0,1,3,4 where 2 is missing , so it has no such order. How to get enum by passing 0,1,3 or 4 in groovy or java.
Just declare a field inside enum as you do in class . And provide a constructor and getter method for the field
What you have is not an ordinal, calling it that will just add confusion. It’s a regular old custom int value
3 Answers 3
Add a field to the enum, and a constructor:
public enum OrderStatus < private Integer codice; public Integer getCodice() < return codice; >private OrderStatus(Integer codice) < this.codice = codice; >OPEN(0), DELIVERED(1), CANCELLED(3), PARTIALLY(4) >
and then you can define a method like this:
public static OrderStatus getByCodice(int codice) < for (OrderStatus tipo : values()) < if (tipo.codice == codice) < return tipo; >> throw new IllegalArgumentException("Invalid codice: " + codice); >
I want a add little bit more to this question, how to save enum value (i.e. 0,1,3 or 4)instead of enum String to the database in grails ??
Record the value in the enum and build a Map to convert.
public enum OrderStatus < OPEN(0), DELIVERED(1), CANCELLED(3), PARTIALLY(4); final int ordinal; private OrderStatus(int ordinal) < this.ordinal = ordinal; >static Map lookup = null; public static OrderStatus lookup(int ordinal) < // Could just run through the array of values but I will us a Map. if (lookup == null) < // Late construction - not thread-safe. lookup = Arrays.stream(OrderStatus.values()) .collect(Collectors.toMap(s ->s.ordinal, s -> s)); > return lookup.get(ordinal); > > public void test() < for (int i = 0; i < 5; i++) < System.out.println(i + " ->" + OrderStatus.lookup(i)); > >
If you need to look up very often then yes! The difference between O(1) and O(n) can be very significant, even for small n if the algorithm is used often. Remember that new statuses can be added later too.
The O(1) and O(n) only tells you how the performance scales with large ns, i.e. what will happen if it changes from one million to two millions. For a single concrete number, it doesn’t say anything, especially for numbers as small as 5 . In fact, an O(n) algorithm can turn out to be way faster than the O(1) alternative. But here, a much simpler solution is possible anyway. Just create an array or list containing the values at their appropriate position (leaving null at index 2 ) and use the lookup int as index…
Java enum value by ordinal
This is the common base class of all Java language enumeration types. More information about enums, including descriptions of the implicitly declared methods synthesized by the compiler, can be found in section 8.9 of The Java™ Language Specification . Note that when using an enumeration type as the type of a set or as the type of the keys in a map, specialized and efficient set and map implementations are available.
Constructor Summary
Method Summary
Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero).
Methods inherited from class java.lang.Object
Constructor Detail
Enum
Sole constructor. Programmers cannot invoke this constructor. It is for use by code emitted by the compiler in response to enum type declarations.
Method Detail
name
Returns the name of this enum constant, exactly as declared in its enum declaration. Most programmers should use the toString() method in preference to this one, as the toString method may return a more user-friendly name. This method is designed primarily for use in specialized situations where correctness depends on getting the exact name, which will not vary from release to release.
ordinal
Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero). Most programmers will have no use for this method. It is designed for use by sophisticated enum-based data structures, such as EnumSet and EnumMap .
toString
Returns the name of this enum constant, as contained in the declaration. This method may be overridden, though it typically isn’t necessary or desirable. An enum type should override this method when a more «programmer-friendly» string form exists.
equals
hashCode
public final int hashCode()
clone
protected final Object clone() throws CloneNotSupportedException
Throws CloneNotSupportedException. This guarantees that enums are never cloned, which is necessary to preserve their «singleton» status.
compareTo
Compares this enum with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. Enum constants are only comparable to other enum constants of the same enum type. The natural order implemented by this method is the order in which the constants are declared.
getDeclaringClass
Returns the Class object corresponding to this enum constant’s enum type. Two enum constants e1 and e2 are of the same enum type if and only if e1.getDeclaringClass() == e2.getDeclaringClass(). (The value returned by this method may differ from the one returned by the Object.getClass() method for enum constants with constant-specific class bodies.)
valueOf
public static Enum> T valueOf(Class enumType, String name)
Returns the enum constant of the specified enum type with the specified name. The name must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.) Note that for a particular enum type T , the implicitly declared public static T valueOf(String) method on that enum may be used instead of this method to map from a name to the corresponding enum constant. All the constants of an enum type can be obtained by calling the implicit public static T[] values() method of that type.
finalize
protected final void finalize()