Key Takeaways
- Java enums, short for enumeration types, are a special type of data that can be used to define a fixed set of constants. These can be used in various places where classes and interfaces are used, such as fields, variables, and parameters.
- Enums in Java can have their own attributes and methods, and can even implement interfaces. They are much more than just constants, functioning more like full-blown classes. They can have fields and methods, and they can implement interfaces.
- All Java enums implicitly extend java.lang.Enum, which provides several useful methods such as values(), valueOf(String), name(), ordinal(), and compareTo(Enum). These methods enable functionalities like returning an array of all enumeration constants, comparing the ordinal values of two constants, and more.
- Java enumerations can be used in identity comparisons and switch statements. They can be compared for identity using the relational operator ‘==’, and can control switch statements, allowing for different actions based on the different possible values of the enum.
Table of Contents
Whatever code you’re working on, chances are you will sooner or later need a list of constants, like Monday, Tuesday, etc. for all weekdays or January, Februrary, etc. for all months. Java has you covered with enum types, usually only called enums, which make it exceedingly easy to define just that. In this article I will teach you everything you need to know to become a proficient user of Java enums.
Enum Fundamentals
In its simplest form a Java enum is just a fixed number of constants that the developer defines while writing the code. (It could, for example, define all SitePoint channels.) Much like a class, an enum defines a type that can be used just about anywhere where classes and interfaces could be used, for example for fields, variables, and parameters.
Enums can actually be much more than mere constants, having their own attributes and methods, but I will come to that later. Seeing them as constants is a good way to get to know them.
Defining an Enum
An enum is defined similarly to how a class would be defined but uses the enum
instead of the class
keyword. The constant values are listed in the enum’s body (meaning within the curly braces). While not necessary, it is common to write the constants in all uppercase letters to make it easier to recognize them.
Now that we have a description for enums, it’s time for an example. Here is what an enum looks like that lists some of the SitePoint channels:
public enum SitePointChannel {
JAVA,
MOBILE,
WEB,
PHP,
WORDPRESS,
JAVASCRIPT,
DESIGN
}
The elements inside the SitePointChannel
enum are called enumeration constants.
Assigning an Enum
Once an enum is defined, you can assign its values to variables. Here is an example:
private SitePointChannel channel;
The channel
field is of type SitePointChannel
, therefore the only values that it can be assigned are those defined by this enumeration. As a local variable that could look as follows:
SitePointChannel channel = SitePointChannel.JAVA;
Using an Enum
Enumerations have a variety of features in Java. One of their core capabilities is that they can be used in identity comparisons and switch
statements.
Identity Comparisons With ==
Enumeration constants can be compared for identity by using the relational operator ==
. Here is an example of an if()
condition, which in this case is always false.
SitePointChannel channel = SitePointChannel.JAVA;
if (channel == SitePointChannel.MOBILE) {
System.out.println("...");
}
Switch Statements
Another very widely used feature of enumerations is the ability to control switch
statements. Here is an example that prints the content of a given channel:
SitePointChannel channel = ... // specify an enumeration constant
switch (channel) {
case JAVA:
System.out.println("Java, web and desktop technologies");
break;
case MOBILE:
System.out.println("Mobile technologies");
break;
case PHP:
// as usual for switch, once a match was found, the execution
// "falls through" to the next branch until it hits a break
case WEB:
case JAVASCRIPT:
case WORDPRESS:
System.out.println("Web technologies");
break;
default:
throw new IllegalArgumentException(
"Unknown channel '" + channel + "'.")
break;
}
In switch
statements, enumeration constants are used without their enumeration type name. This is due to the fact the enum type is implicitly specified in the switch
expression. It is good practice to list all enum constants (even if some of them don’t do anything) and add a default branch, usually with an exception (in case a new constant gets added and someone misses the switch statement and doesn’t update it.)
Enums as a Class
With the basics of Java enums covered we can go beyond the interpretation of enums as a fixed number of constants. Enums are, in fact, much more like classes!
They can have fields and methods as well as implement interfaces and I will explain all of that in a minute. Even the enumeration constants are not that special – they are just public, static, and final members of their enum type. The only reason we don’t have to put public static final
in is that the compiler fills it in for us.
The major differences towards regular classes is that they can not extend other classes (see below why) and can not be created with the new
keyword (to keep the number of constants fixed).
Extending java.lang.Enum
All enums implicitly extend java.lang.Enum
. In Java, a class can only extend one parent and therefore an enum cannot extend any other class (but implement interfaces – see below).
Extending Enum
means that every enum has a few methods that make it more usable:
- static
values()
- static
valueOf(String)
name()
ordinal()
compareTo(Enum)
Enum
‘s values()
Method
The values()
method returns an array of enum-type variables containing all of the enumeration constants. Here is an example:
SitePointChannel[] channels = SitePointChannel.values();
for (SitePointChannel channel : channels) {
System.out.println(channel + " Channel");
}
And the output:
JAVA Channel
MOBILE Channel
WEB Channel
PHP Channel
WORDPRESS Channel
JAVASCRIPT Channel
DESIGN Channel
As you can see, the values()
methods provides a nice solution to loop over all constants of an enum.
Enum
‘s valueOf(String)
Method
The valueOf(String)
method returns an enumeration constant whose value corresponds to the string passed to it or throws an IllegalArgumentException
if no constant with the specified name was found. Careful, the strings passed to valueOf
are case sensitive!
// returns SitePointChannel.JAVA enum
SitePointChannel.valueOf("JAVA");
// throws IllegalArgumentException
SitePointChannel.valueOf("java");
As pointed out previously, all enumerations automatically inherit java.lang.Enum
. This class defines several methods, available for all the enumerations.
The name()
method
This method returns the name of this enum constant, exactly as declared in its enum declaration. Here is an example:
SitePointChannel channel = SitePointChannel.JAVA;
System.out.println(channel.name());
The output of this example is the String JAVA
.
The ordinal()
method
This method is used to obtain an enumeration constant’s position in the list of constants. This is called the ordinal value. Here is an example:
SitePointChannel channel = SitePointChannel.JAVA;
System.out.println(channel.ordinal());
The output of this example is “0” since JAVA
is the first constant of the Sitepoint
enum and the initial constant is assigned an ordinal of zero. Hence, the following outputs “3”:
SitePointChannel channel = SitePointChannel.PHP;
System.out.println(channel.ordinal());
The compareTo(Enum)
method
This method is used to compare the ordinal value of two constants of the same enumeration. This method returns a negative integer, zero, or a positive integer based on the ordinal positions of the two instances that are being compared.
This is how this works. Let’s take, for example, as a reference enum instance SitePointChannel.PHP
.
SitePointChannel channel = SitePointChannel.PHP;
Surely if we compare the channel
instance with SitePointChannel.PHP
, the compareTo()
method will return the value 0.
// returns 0
channel.compareTo(SitePointChannel.PHP);
Since the reference enum instance is in the fourth position in the enum class and has both elements prior and subsequent to its position, it can return both positive and negative outputs with this method.
For example, if it is compared with SitePointChannel.JAVA
, the output of the compareTo()
method will be positive since SitePointChannel.JAVA
is located before the reference instance:
// actually returns 3
channel.compareTo(SitePointChannel.JAVA);
If the reference enum instance is compared with instances that come after it in the enum class, it will return a negative value. For example, comparing it to SitePointChannel.JAVASCRIPT
will return the value -2.
// returns -2
channel.compareTo(SitePointChannel.JAVASCRIPT);
Enums with Fields
Java enumeration constants can have fields, which must be given a value at creation time. Keep in mind that as with instances of a regular class, each enumeration constant has its own fields. In order to define values, the enclosing type must have a constructor that accepts parameters. As I mentioned earlier, each enumeration constant is an object of its enumeration type, so a constructor is called for each of the enumeration constants. Fields and constructors (as well as methods) must be defined below the list of constants.
Let’s go through an example for this problem. Suppose we have the SitePointChannel
enumeration with the list of channels and we need to add to each channel the number of published articles. I will declare a field for it:
public enum SitePointChannel {
JAVA,
MOBILE,
WEB,
PHP,
WORDPRESS,
JAVASCRIPT,
DESIGN;
private int numberOfArticles;
}
So far, so good, but the field is never assigned a value. To do that we also need a constructor:
// DOES NOT COMPILE
public enum SitePointChannel {
// [...] list of constants as before
private int numberOfArticles;
Sitepoint(int numberOfArticles) {
this.numberOfArticles = numberOfArticles;
}
}
Unfortunately this does not compile because the constants are initiated with the no-args constructor that no longer exists. To fix this, we call the new constructor:
public enum SitePointChannel {
JAVA(1344),
MOBILE(2444),
WEB(4311),
PHP(5311),
WORDPRESS(3221),
JAVASCRIPT(3865),
DESIGN(3492);
// [...] field and constructor as before
}
The same logic is true for multiple instance variables and different data types (int
, double
, String
, …).
Enums with Methods
Besides the basic method available to all enums you can add custom methods to add additional functionalities.
The following example demonstrates the usefulness of enums with methods. Previously in this article, I mentioned that the valueOf()
method is case sensitive. The following solution will give an alternative solution to the valueOf()
method without the limitations of case sensitivity, by creating our own method.
public enum SitePointChannel {
JAVA,
MOBILE,
WEB,
PHP,
WORDPRESS,
JAVASCRIPT,
DESING;
public static SitePointChannel valueOfIgnoreCase(String channelName) {
channelName = channelName.toUpperCase();
return valueOf(channelName);
}
}
To make sure this solution works, run the following code snippet.
if (SitePointChannel.valueOfIgnoreCase("jaVa") == SitePointChannel.JAVA){
System.out.println("Ignore case enum");
}
As you can see from the example, the valueOfIgnoreCase()
function takes the string “jaVa” and returns the JAVA
enum. This solution works for any combination of uppercase and lowercase characters of a string representing a SitePointChannel
enum instance.
Implementing interfaces
Given the ability to have fields and methods it makes sense that enums can also implement interfaces. This works exactly like it would in regular classes so there is little to be said about it.
Here’s a simple example:
public interface Printable {
void print();
}
public enum SitePointChannel implements Printable {
// [...] constants, field and constructor as before
@Override
public void print() {
System.out.println("Channel " + name()
+ " has " + numberOfArticles + " articles.");
}
}
Summary
That’s all on the fundamentals of Java enums. We saw that they can describe a fixed number of constants and how Enum
‘s methods values()
, valueOf(String)
, name()
, ordinal()
, and compareTo(Enum)
can be used. But we also discovered that they are full-blown classes, which allow adding fields, creating methods, and implementing interfaces.
Frequently Asked Questions (FAQs) about Java Enum Types
What is the significance of Java Enum Types?
Java Enum types, also known as enumerated types, are a special kind of data type that enables a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. Enum types are used when we know all possible values at compile time, such as choices on a menu, rounding modes, command line flags, etc. It is not necessary that the set of constants in an enum type stay fixed for all time.
How do you define an Enum in Java?
In Java, you can define an Enum using the keyword ‘enum’. The general form of an enum type is:enum EnumName {
CONSTANT1,
CONSTANT2,
...
CONSTANTN
}
Each of the constants is declared with the enum type and can be used as a standalone constant.
Can Enum be null in Java?
Yes, an Enum can be null in Java. However, if you try to invoke a method on a null enum, a NullPointerException will be thrown. It’s always a good practice to check if an enum is not null before invoking methods on it.
How do you compare Enum values in Java?
In Java, you can compare Enum values using the ‘==’ operator or the equals() method. Both will return true if the two enum values being compared are equal. Here’s an example:if (Day.MONDAY == Day.MONDAY) {
System.out.println("True");
}
This will print “True” because both enum values are the same.
Can Enum have methods in Java?
Yes, Enum in Java can have methods. You can declare abstract methods within enum and let specific constants provide the implementation for these abstract methods. Here’s an example:public enum Day {
MONDAY {
public void printMessage() {
System.out.println("Mondays are bad.");
}
},
FRIDAY {
public void printMessage() {
System.out.println("Fridays are better.");
}
};
public abstract void printMessage();
}
In this example, each constant provides a different implementation for the printMessage() method.
How do you iterate over an Enum in Java?
You can iterate over an Enum in Java using the values() method, which returns an array containing all of the enum’s values in the order they’re declared. Here’s an example:for (Day day : Day.values()) {
System.out.println(day);
}
This will print all the days of the week.
Can Enum implement interfaces in Java?
Yes, an Enum in Java can implement an interface. This allows you to add more functionality to your enums. However, an Enum cannot extend another Enum or any other class because it implicitly extends the Enum class.
Can Enum be serialized in Java?
Yes, Enum in Java is serializable. When an enum is serialized, only the name of the enum constant is serialized. When the enum is deserialized, the name is used to find the corresponding enum constant.
Can Enum have a constructor in Java?
Yes, Enum in Java can have a constructor. However, the constructor must be either private or package scope. You cannot use public or protected constructors for an Enum. The constructor is called when the enum constants are created.
Can Enum be used in a switch statement in Java?
Yes, Enum can be used in a switch statement in Java. This can be very useful when you want to perform different actions based on the different possible values of the enum. Here’s an example:switch (day) {
case MONDAY:
System.out.println("Mondays are bad.");
break;
case FRIDAY:
System.out.println("Fridays are better.");
break;
}
In this example, a different message is printed depending on the value of the ‘day’ variable.
Valdio recently graduated in Computer Engineering. He is a mobile developer, who is passionate about mobile technologies and learning new things. He has worked with languages such as C, Java, php and is currently focused on Java, mobile and web development