A Short Primer on Java Enums - part 1

In his JavaOne talk this year, Josh Bloch gave some very useful tips about using enums in Java. Here is my take on enums, and how to use them to represent simple value lists which would otherwise be stored in code tables. This document is in two parts - Part one covers the basics of Java enums, and Part 2 goes into more advanced use cases such as using enums with Hibernate.

Introducing Java enums

An enum represents a pre-defined list of static values. Most applications have lots of places where you need this sort of thing. Colours, states, font-styles - the list is endless. A common older approach (required before Java 5) was to define lists of static values is to use integer constants, as shown here:

public class Issue {
public static final int STATUS_OPEN = 1;
public static final int STATUS_CLOSED = 2;
public static final int STATUS_REOPENED = 3;

private int status;

public void setStatus(int status) {
this.status = status
}
...
}

 

However, this is a very poor solution, for many reasons, that Josh discusses in some detail in his Effective Java book. For example, there is no type safety. You can use any integer value in this field, which can result in errors, eg:

    issue.setStatus(4); // This is wrong!

 

In addition, the solution is fragile. These values are integers, so they will be compiled into the classes that use them. Should you modify the int value associated with a particular constant, the client classes will not automatically recompile. And if the client classes are not recompiled, they will continue to use the old values, which will result in strange errors.

 

Luckely, in Java 5, you can use enums for a much more type-safe approach. An enum is basically a type-safe, pre-defined list of values, which you can define as follows:
public enum Status {
Open, Closed, Reopened
};

 

You can define an enum in the same way as you would a class. Enums that are used by many classes should be defined as public, stand-alone classes, defined in their own *.java file. Enums that are only used by a particular class, on the other hand should be defined as public inner classes, as shown here:

public class Issue {

public enum Status {
Open, Closed, Reopened
};

private Status status;

public Status getStatus() {
return status;
}

public void setStatus(Status status) {
this.status = status;
}
...
}

 

On of the great things about this is how typesafe it all is. You can use an enum like this as follows:

        Issue issue = new Issue();
issue.setStatus(Issue.Status.Closed);
assertThat(issue.getStatus(), is(Issue.Status.Closed));

 

Here, you cannot fail to put a legal value into the status field, as it is verified by the compiler. For example, the following code, where we try to assign an Importance value to the Status field, simply won't compile:

        Issue issue = new Issue();
activity.setStatus(Issue.Importance.Low); // This will not compile

 

Of course, if you use static imports, the code is even simpler:

import static com.mycompany.Issue.Status.Closed;
...
Issue issue = new Issue();
issue.setStatus(Closed);

 

Listing enum values

Now there are times that you might need to list the values in an enumaration. For example, you may want to create a list of entries in a SELECT element on an HTML page. You can do this with the static

values()
method, as shown here:
        ActivityStatus[] values = ActivityStatus.values();
for(ActivityStatus status : values) {
System.out.println(status);
}

 

This will produce the following list:

Open
Closed
Reopened

 

Easy! Note that the enum values are displayed in their natural order (their order of appearance in the Java class), not in alphabetical order. This means you can define an implicit order, and not worry about having to add an extra field to define the order manually.

Conclusion

So now, we've covered some of the basic uses of enums. In the next part of this article, we will look at more advanced uses of enums, such as how they integrate with Hibernate.

John is a freelance consultant specialising in Enterprise Java, Web Development, and Open Source technologies, currently based in Wellington, New Zealand. Well known in the Java community for his many published articles, John helps organisations to optimize their Java development processes and infrastructures and provides training and mentoring in open source technologies, SDLC tools, and agile development processes. John is principal consultant at Wakaleo Consulting, and runs several Training Courses on open source Java development tools and best practices. John is a DZone MVB and is not an employee of DZone and has posted 57 posts at DZone. You can read more from them at their website.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

nitin pai replied on Mon, 2008/05/19 - 11:47am

Hey John, This article has appeared at the right time when I needed to know about Enums. I would like to know how to use Enums in this case: I have to make a range comparison and I think Enums might be helpful here. I want something like this (functionally): Enum STATUS{ STATUS1 (10,20), STATUS2 (20,30) } while in the program i need : int value = STATUS(12).getStatus(); I should get the value as STATUS1. Is it possible to do so? Please show how can this be done?

Mwanji Ezana replied on Tue, 2008/05/20 - 6:04am

You could declare a valueOfInRange(int) kind of method on the enum, which would find the enum corresponding to the value you passed in (take a look at the default valueOf() method). e.g.:

STATUS.valueOfInRange(12) would return STATUS1

STATUS.valueOfInRange(23) would return STATUS2

You'd have to decide what to do with 20, which currently belongs to both instances (or maybe that's just a typo?).

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.