Fundamentals of Java Enum Types

Share this article

Fundamentals of Java Enum Types

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 for a list of sonstants - traffic lights, maybe?

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 VeliuValdio Veliu
View Author

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

nicolaip
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week