The Complete Java Enums Tutorial with Examples
This tutorial explains the fundamentals of Java enums with examples. It starts with defining enum types. Next it explains where enums can be defined - in a class file of their own, alongside another class definition, or as a member of another class. Next the
Let us break the above definition down into the terms used in it to make it simpler -
Defining an Enum
Let us take the
Important points to note in above enum definition
Let us now quickly take a look at all the features which the Java compiler provides to an enum type -
OUTPUT of the above code
Explanation of the code
Using the static valueOf() method of an enum
Static
In case the string passed as parameter to
OUTPUT of the above code
Explanation of the code
Benefits of using enums
Enums restrict the values to the defined constants and this is a huge benefit from a system designer's point of view. A system designed for 4 departments will only allow these 4 values to be assigned to any variable of type
Lets say we need to define a 'Department Code' for evey
The enhanced enum with a new private instance variable
An important point to note about enum constructors: All enum constructors, including of course the
To check whether the newly added method, variable and constructor are working fine let us iterate through the
OUTPUT of the above code
As we can see above, department codes were passed via the constructor and assigned to individual enum constant's
This requirement now requires us to change the behavior of
Lets now change our
OUTPUT of the above code
As we can see above, the overridden logic for
Design Note - In case you want every enum constant to override some method and do it in a mandatory manner, then you can make that method in enum definition as abstract. This will force all enum constants to mandatorily override this method with their own custom logic.
Enums and switch-case
One of the commonly used applications of enums is when deciding between multiple execution paths using switch-case statements. When the decision on which execution path to take can be reduced to a single enum constant value, then using that enum type in switch statement and specifying logic to execute for each of the enum constants of that type using a corresponding case is an efficient option to implement.
The code snippet shown next has a method which prints different outputs for each of the four department types based on which
OUTPUT of the above code
Summary
In the above tutorial we understood enums in their entirety. Starting from the basics we looked at what are enums, how to define an enum, enum constant naming convention, where to define enums, using the static
values()
and valueOf()
static methods of enum are covered, along with the ordinal()
method, with code examples to show the methods' usage. Enum equality is then touched upon briefly along with benefits of using enums. After covering the basics of Java enums, the tutorial then moves on to explain enhanced enums with variables, methods and constructors with detailed code examples. It then covers the topic of specific method overriding for an enum constant, aka constant specific class body, with examples. Lastly, the tutorial shows how enums can be efficiently used to decide between multiple execution paths when using switch-case statements.
What are enums
Enums are types which represent a fixed set of related constants.
- Fixed Set - Enums have a fixed number of values specified upfront when defining an enum type.
- Related Constants - The fixed set of values are for a given enum type defined. Hence, these enum values are related by their common enum type.
- Enums are types - Enums are types in themselves; they are in fact special types of classes.
- Departments in an Organization -
HUMAN RESOURCES
,MARKETING
,IT
,OPERATIONS
are all departments of an organization. Hence, for aDepartment
enum the fixed set of enum values are the department names. - Sizes of Shirts -
SMALL
,MEDIUM
,LARGE
,EXTRA_LARGE
are all sizes which a shirt can take. Hence, for aShirtSize
enum the fixed set of enum values are the various shirt sizes.
Department
enum from the 1st example we saw above and start building upon it. To start with, defining a fixed set of constant values for departments as an enum is as simple as writing the following code - Simplest enum definition
public enum Department {
HR, OPERATIONS, LEGAL, MARKETING //; semi-colon is optional here
}
Department
enum has four values -HR
,OPERATIONS
,LEGAL
,MARKETING
.- The 4 department constants can be accessed as
Department.HR
,Department.OPERATIONS
and so on.(Note - The syntax to access enums can vary based on where enums are defined which will be covered shortly.) - Semi-colon(;) at the end of enum constants is optional unless you decide to add more to the enum in terms of variables, methods etc., which will be covered further down under the topic enhanced enums.
- It is important to note at this stage that
Let us now quickly take a look at all the features which the Java compiler provides to an enum type -
- All enums implicitly extend
java.lang.Enum<E>
. - Methods
name()
,ordinal()
andvalueOf()
, inherited fromEnum<E>
, are available on all enums. - Enum objects cannot be created explicitly except by using reflection.
- Boilerplate code includes the definition of a fixed set of instance variables which are
public
static
final
objects corresponding to each of the enum constants defined for that type. - Static
values()
method is available on all enum types. When invoked on an enum type,values()
method returns an array of all enum constants defined for that enum type. toString()
method, overridden automatically by the compiler for all enum constants, returns the name of the enum constant as a string by default.- Enums can be used in switch-case statements (explained with code example further down).
- Enums can be defined independently(as a top-level class)
- In a file which contains only the enum definition
Enum defined in a separate Java file
//In file - Department.Java public enum Department { HR, OPERATIONS, LEGAL, MARKETING } //In file EnumTest.java public class EnumTest { public static void main(String args[]) { Department enumVar = Department.HR; } }
Department.java
file contains only theDepartment
enum definition.Department
enum can be defined withpublic or default
access in this case.- An enum constant of
Department
type can be accessed using the syntax -<enum-name>.<constant-name>
. For example, in the above program the enum constants ofDepartment
can be accessed as -Department.HR
,Department.OPERATIONS
, and so on. - In the class
EnumTest
, a variable of typeDepartment
is defined asenumVar
, which is assigned the HR Department using syntaxDepartment.HR
.
- enum definition can accompany another class definition in that class' file
Enum defined alongside another class in same file
//In file Employee.java enum Department { HR, OPERATIONS, LEGAL, MARKETING } public class Employee { String name; Integer age; Double salary; }
Employee.java
file containsEmployee
class definition along withDepartment
enum definition.Department
enum can be defined with onlydefault
access in this case, as only a type which is named after the file name(Employee
class in this case) can bepublic
in Java.- An enum constant of
Department
type can be accessed using the syntax -<enum-name>.<constant-name>
. This is same as that for previous enum definition in its own file, as both this enum and previous one are not defined as member of another class.
- In a file which contains only the enum definition
-
Enums can be defined as members of a class aka 'nested enum types'.
Nested enum defined as member of a class
//In file Employee.java public class Employee { enum Department { HR, OPERATIONS, LEGAL, MARKETING; } private String name; private Integer age; } //In file EnumTest.java public class EnumTest { public static void main(String args[]) { Employee.Department enumVar = Employee.Department.HR; } }
Employee.java
file containsEmployee
class definition.Department
enum is defined insideEmployee
class.Department
enum in this case can be defined with any desired access, (i.e.public
,private
,default
), here.Department
enum defined above is a nested enum type as it is 'nested' inside another class. Nested enum types are implicitly static, and hence mentioning static in their definition is actually redundant.- An enum constant of static nested enum
Department
type can be accessed using the syntax -<enclosing-class-name>.<enum-name>.<constant-name>
. For example, in the above program the enum constants of Department can be accessed as -Employee.Department.HR
,Employee.Department.OPERATIONS
, and so on. - In the class
EnumTest.java
, a variable of typeEmployee.Department
is defined asenumVar
, which is assigned the HR Department accessed using syntaxEmployee.Department.HR
.
Department
type above has 4 constant instances - HR
, OPERATIONS
, LEGAL
, MARKETING
. Now any variable defined in any class which is of type Department
can have only one of these 4 constant values.
Using the static values() method of an enum
The static values()
method is a very handy method as it is available on every enum type, and when invoked it returns an array of all enum constants of that enum type. Lets see a code example showing the use of values()
method.
Example showing enum's values() method usage
public class EnumTest {
public static void main(String args[]) {
for(Department dept:Department.values()){
System.out.println("Enum constant-> "+dept+" with ordinal value-> "+dept.ordinal());
}
}
}
Enum constant-> HR with ordinal value-> 0 Enum constant-> OPERATIONS with ordinal value-> 1 Enum constant-> LEGAL with ordinal value-> 2 Enum constant-> MARKETING with ordinal value-> 3
- Example uses the enum
Department
which we defined in a file of its own. - Using a
for loop
, the constants inDepartment
enum are iterated through. Each enum constant's value and ordinal position is printed as it is encountered.
What is ordinal value of an enum constant
Ordinal value of an enum constant, accessed using the syntax
<enum-constant>.ordinal()
is an int value equal to the enum constant's ordinal position in enum declaration, starting from the value 0(zero).
valueOf()
method, which can be invoked on the enum type, takes a single String
parameter which needs to be the name of any of the constants of the enum on which this method is invoked. It returns an enum constant object whose name matches the name value passed as parameter.In case the string passed as parameter to
valueOf()
method is not a valid name of one of its constants then a java.lang.IllegalArgumentException
is thrown.
"Example showing enum's valueOf() method usage
public class EnumTest {
public static void main(String args[]) {
Department enumVar = Department.valueOf("HR");
System.out.println("enumVar == Department.HR? "+(enumVar == Department.HR));
System.out.println("enumVar equals Department.HR? "+(enumVar.equals(Department.HR)));
}
}
enumVar == Department.HR? true enumVar equals Department.HR? true
- Example uses the enum
Department
which we defined in a file of its own. enumVar
is a variable of typeDepartment
which is assigned the object returned by invokingvalueOf()
method onDepartment
with"HR"
as value for name parameter.- On equating
enumVar
withDepartment.HR
, using both==
andObject.equals()
method, the enum constants are found be equal.
Determining equality of 2 enum variables
2 enum variables can be compared with either the
‘==’
or the ‘equals()’
method, without the need to override Object.equals()
method in the enum definition.
Department
used anywhere in the whole system. This prevents a lot of potential defects and improves code maintainability.
Moving beyond the basic enum to enhanced enums
Having seen how to define a basic enum and how to use it in code, it is now time to explore the full potential of an enum as a 'type'. As we understood above, enums are nothing but classes albeit that of a 'special' type. So, by virtue of being a class, an enum type can also have methods, variables and constructors defined in it. One can also selectively override method definitions for specific enum constants. Let us look at these advanced features of enums now.Lets say we need to define a 'Department Code' for evey
Department
enum constant. This code will be alphanumeric and so we will store it as a String
. Just like in a class definition, we can create a private instance variable for department code in Department
enum, along with a getter method for fetching this value. In addition, we will also define a constructor for passing the department code at the time of defining the enum itself.The enhanced enum with a new private instance variable
deptCode
holding the department code, a getter method for deptCode named getDeptCode()
, and a constructor which accepts the department code at the time of enum creation would look like this.
Example showing an enum with an instance method, variable, constructor
public enum Department {
HR("DEPT-01"), OPERATIONS("DEPT-02"), LEGAL("DEPT-03"), MARKETING("DEPT-04");//semi-colon is no longer optional here
Department(String deptCode){
this.deptCode=deptCode;
}
private String deptCode;
public String getDeptCode(){
return deptCode;
}
}
Department
enum constructor defined above, are implicitly private. So, even in case there is no access modifier defined for an enum constructor (as is the case in example shown above), the compiler implicitly assumes it to be private. Also, note that defining an enum constructor with public or protected access would result in a compiler error.To check whether the newly added method, variable and constructor are working fine let us iterate through the
Department
enum constants using the static values()
method we saw earlier and print the department constants along with code.Example iterates through constants of enum with constructor
public class EnumTest {
public static void main(String args[]) {
for(Department dept:Department.values()){
System.out.println("Department name: "+dept+" Department Code: "+dept.getDeptCode());
}
}
}
Department name: HR Department Code: DEPT-01 Department name: OPERATIONS Department Code: DEPT-02 Department name: LEGAL Department Code: DEPT-03 Department name: MARKETING Department Code: DEPT-04
As we can see above, department codes were passed via the constructor and assigned to individual enum constant's
deptCode
instance variable, which was then printed correctly when we iterated over Department
enum using static values()
method.
Enum with selective instance method overrides
To understand this feature of enums, let us now extend the department use case a little. The HR department on seeing the above output where all department codes are accessible publicly has raised an exception to its code being visible to all. It has asked that only its department code should be shielded from any public access attempts such as using the values()
method call, and instead of actual deptCode
value the string "NOT ACCESSIBLE"
be returned.This requirement now requires us to change the behavior of
getDeptCode()
method for only the enum constant HR
. Fortunately, enum does provide selective override of methods for specific constants. Lets see how it works.Lets now change our
Department
enum definition and write a constant specific class body for HR
enum constant for overriding the getDeptCode()
method. We will then iterate again through the enum constants using values()
method, and see if department code for HR is shielded as per requirement or not.
Example showing constant specific class body implementation
//Department.java
public enum Department {
@Override
HR("DEPT-01"){
public String getDeptCode(){
return "NOT ACCESSIBLE";
}
}, OPERATIONS("DEPT-02"), LEGAL("DEPT-03"), MARKETING("DEPT-04");//semi-colon is no longer optional here
Department(String deptCode){
this.deptCode=deptCode;
}
private String deptCode;
public String getDeptCode(){
return deptCode;
}
}
//EnumTest.java
public class EnumTest {
public static void main(String args[]) {
for(Department dept:Department.values()){
System.out.println("Department name: "+dept+" Department Code: "+dept.getDeptCode());
}
}
}
Department name: HR Department Code: NOT ACCESSIBLE Department name: OPERATIONS Department Code: DEPT-02 Department name: LEGAL Department Code: DEPT-03 Department name: MARKETING Department Code: DEPT-04
As we can see above, the overridden logic for
getDeptCode()
we specifically added to the enum constant HR in curly braces, did indeed override the default getDeptCode()
implementation for only HR enum constant. The code for HR Department was printed in output as "NOT ACCESSIBLE"
just as we wanted.Design Note - In case you want every enum constant to override some method and do it in a mandatory manner, then you can make that method in enum definition as abstract. This will force all enum constants to mandatorily override this method with their own custom logic.
The code snippet shown next has a method which prints different outputs for each of the four department types based on which
Department
enum constant is passed to the switch statement as input. EnumTest
class iterates through the Department
enum constants using the values()
method, so that each of the enum constants is encountered exactly once.Example showing use of enum in switch-case
public class EnumTest {
public static void main(String args[]) {
for (Department dept : Department.values()) {
switch (dept) {
case HR:
System.out.println("Case - HR");
break;
case OPERATIONS:
System.out.println("Case - OPERATIONS");
break;
case MARKETING:
System.out.println("Case - MARKETING");
break;
case LEGAL:
System.out.println("Case - LEGAL");
break;
}
}
}
}
Case - HR Case - OPERATIONS Case - LEGAL Case - MARKETING
values()
and valueOf()
method of enums, enum equality and ordinal values. We then looked at enhanced enums containing variables, methods, constructors and constant specific class body. Lastly, we saw how enums can be used to write conditional logic using switch-case statements.