enum : Java Glossary


enum
Java version 1.5 or later has built-in support for enumerated types. Prior to that you had to kludge them in some way with static final ints (which were not typesafe) or with Objects which would not work in switch statements.
Enum Basics Nested enums
Sample Code Under The Hood (1)
Advantages Under The Hood (2)
Disadvantages Under The Hood (3)
Common Methods Encapsulation
Inheritance Serialization
To & From Ordinal The Good
Built-in Methods The Bad
Scope of Enum variables Alias Values
Sorting Enums Data Bases
Individual Methods Legacy
Keying enums in a GUI General Purpose Enum Code
Getting Fancy Learning More
Gotchas Links

enum Basics

Don’t confuse enum with the Enumeration interface, an almost obsolete way of iterating over Collections, replaced by Iterator.

Java version 1.5 enums are references to a fixed set of Objects than represent the various possible choices. enums handle single choices, not combinations of choices. For combinations, you need EnumSet. For HashMap-style lookups when the key in an enum, you need EnumMap.

Enum and the enum constants are just classes. Since enum constants are constants, normally they should be all capitalised. However, since the constant name is the same as what is displayed externally, some people relax that rule and name constants with upper or lower case names as appropriate for the application. Note that you can’t call your enums default or null since these are reserved words. Try usual or none.

enums you want widely known should be put in the their own source file and given the attribute public. You then import the enum, as you would any other class.

Needless to say, enums are type safe. If you try to store an enum constant for a dog Breed into a Locomotive type enum variable, the compiler will refuse.

Sample Code using enum

Advantages

The advantages of enums over an array of Strings are:

Disadvantages

The disadvantages of enums over an array of Strings are:

enum Constants Can Have Common Methods

In this simple example, the enum constants each have an instance field colours and an instance method getColours.

Inheritance

enums are rather limited in use of inheritance.

To & From Ordinal

// T O   A N D   F R O M   O R D I N A L

// To Ordinal
Breed dog = Breed.LABRADOR;
int ordinal = dog.ordinal();  // LABRADOR = 2

// From Ordinal
int ordinal = 2;
Breed dog = Breed.values()[ ordinal ];   // LABRADOR = 2

Built-in Methods

All enums and enum constants have some built-in methods:

Scope of enum Variables

enums can have static variables shared between all enum constants and instance variables. Nested enums can access the static final constants and static variables of the enclosing class, but not its instance variables. static and instance methods behave similarly. Implicitly, a nested enum is a nested static class. Here is an example to demonstrate these rules:

You cannot place static final constants ahead of your enum definitions. Neither can you place them afterwards and use the values of those static finals in your enum definitions. You have to place them in some other class.

Sorting enums

You sort an array of enum values the same way you would an array of Object of some particular class. By default, Java sorts by ordinal. You can define your own Comparators as in this example:

You can of course also sort Collections of enums in the obvious way. I have not figured out how to implement Comparable with enums, but even if I could, it would probably not be wise to override the default. It would just confuse people reading the code.

enum Constants Can Have Individual Methods

There are three basic ways to write a method for use by an enum constant:
  1. Single common method for all enum constants. It works with different constants passed in the constructor. The method is part of your enum class as a whole.
  2. An abstract or default method in the enum class as a whole, and each enum constant overrides it.
  3. enum constants have peculiar methods all their own. If two enum constants implement the same method, they are only incidentally related.
The individual enum constants with methods are implemented as and behave like little anonymous classes. That is how the individual methods can override methods common to the enum as a whole, and how the enum methods have access to the fields of the enum as a whole as well as their own fields. Further, the scope rules of visibility and how the scope modifiers such as public and private work the same way as for anonymous inner classes.

Keying enums in a GUI (Graphic User Interface)

Here is how to let the user select an enum in a GUI using JComboBox.

Getting Fancy

enum constants can even each have their own little anonymous inner class complete with constructors, methods and variables. See the Under the Hood (3) example below.

I use enums for writing the finite state automata that colourise all the listings on my website. Each state is represented by one enum constant. Each enum constant has custom logic to figure out the next state. The enum as a whole has both static and instance methods, and the enum constants override some of the instance methods. That allows a default implementation for a method that all enum constants must implement. I can invoke the method by the common base name, just as with classes and subclasses.

It is easiest to use public or top-level enums. Begin your experiments with public enums in their own *.java file to avoid frustration. I have managed to get nested static enums and nested inner enums to work as well, at least for the simple case where the enum constants have no constructors or individual classes. Even when you don’t specify static, nested enum classes are considered static. They don’t require an associated outer class object. There are no such thing as anonymous enums, and if there were, they would not be very useful since their enum constants would be anonymous too.

Unlike most of Java, you need to understand how enums work under the hood. When you understand the inner class structure, everything makes sense. Without that understanding enums will drive you insane with bizarre behaviour and restrictions.

Gotchas

You cannot define static finals in an enum and use them in the enum constructors. You can put them in a separate private static nested class or a separate class. I find it works best to put nothing but such static finals in the auxiliary class.

You cannot put references to the enums in your separate class of static finals. They need to go in the main enum class, after the enum constants. Initialisation must proceed in this order:

  1. Evaluate the static finals referenced in the enum constructors.
  2. Evaluate the enum constructors.
  3. Evaluate the static finals that reference the enum constants.

Nested enums

An enum is a species of class, so it can be a public class, a top level default class or a nested static class. Inner class enums are considered static even if you don’t use the static keyword. An enum follows the same scope and visibility rules as any other class.

I recommend using only public enums and putting them each one in its own *.java file. However, you can also create toplevel enums, and static enums like this:

All enums support both static and instance fields and methods of the enum as a whole. However, enum constants are fields that point to unique objects of the enum class with optional anonymous inner classes. They can thus include instance fields and methods, but not static, simply because for some idiotic reason all inner classes can’t support static fields and methods. Some believe the reason statics are not implemented was not laziness but rather a desire prevent programmers from using inner classes for purposes other than serving the outer class. One speculated the problem comes because there are actually two flavours of anonymous classes, those declared in a static and an instance context. Another explanation is that you run into chicken and egg initialisation problems if you allow static members.

Under The Hood (1)

Here is a simple program using enums and a switch. I have provided a commented decompilation so that you can see how enum pulls off its magic.

Here is a decompilation of the above code. Note how the Breed enum is, underneath, just an ordinary class that extends the abstract class java.lang.Enum<E extends Enum<E>>.

I wondered wonder why Sun didn’t just use the enum ordinals directly as case numbers. The tableswitch JVM (Java Virtual Machine) instruction does an indexed lookup, which would be one level of indirection less than Oracle’s enum scheme. Perhaps Sun was worried the compiler would sometimes generate a slower lookupswitch if the table were not dense or if it were large. With their preconditioning, they guarantee the table is both small and dense, which guarantees that the faster tableswitch instruction will be used. Sun could refine its technique by collapsing the lookupswitch table further by using the same case number for multiple case labels on the same code. Others have pointed out Oracle’s indirect scheme provides additional binary compatibility. If class A has a switch statement involving enum B, and B acquires a new enum constant, even one in the middle of the enumeration order, and A is not recompiled, the switch will still work (treating the new enum constant as part of the default category.

Under The Hood (2)

Here is a simple program using enum where the enum constants all use the same implementation of the same method and same instance field. I have provided a commented decompilation so that you can see how enum pulls off its magic.

Under The Hood (3)

Here is a simple program using enum where the one enum constant implements a method that the other enum constants do not. I have provided a commented decompilation so that you can see how enum pulls off its magic.

Encapsulation

What if you had three enum classes that shared a lot of identical code. How could you encapsulate it to avoid the repetition?

Serialization

Enums can be serialized. The usual serialization process would not be sufficient since it would result in an enum variable being reconstituted to point to a clone of the enum constant from the source machine rather than to the corresponding enum constant in the target machine. The serialization process gets around this problem by serializing as the enum constant name (a String), along with information identifying its base enum type. Deserialization behaviour differs as well — the class information is used to find the appropriate enum class, and the Enum. valueOf method is called with that class and the received constant name in order to obtain the enum constant to return.

This technique makes serialized files more stable that had it been based on using ordinals to represent the value. With Oracle’s technique you can add new enum constants, or change the enum methods, and you can still read old serialized files with new code.

Other ways of externalising enums for serialization or storing in files and databases include:

The Good About enums

The Bad About enums

Alias Values

Here is a simplified version of a program that lets you create a valueOf that accepts aliases 

Data Bases

How do you deal with storing enums in databases? Here are ways I would not recommend: Here are ways I would recommend: In your enum, you have a valueOf variant that accepts the database 2-char abbreviation using a hash-map constructed at load time from values() list. The 2-char names are defined in the enum constant constructors. This allows you to rapidly interconvert between enum ⇔ 2-char ⇔ internationalised String.

Storing invariant two-char codes in your SQL database will protect you from the main catastrophic error — out by one on your enum constants without noticing.

If a database contains an invalid 2-char code, you will detect the problem the instant your code encounters it. The error won’t stealthily skulk under the murk the way using ordinals permits.

Don’t use default in your switches. Then the compiler will notify you if you did not insert code to handle the new enum case.

If you use Applets, your client code can convert 2-char enums to internationalised strings. If you don’t, then your Servlets can do it. This should be considerably faster than getting your SQL database to do it by table look up.

Legacy

enums arrived rather late in the game, not until Java version 1.5. By this point, most of the Java class library was already established. This is why it so rarely uses enums. It uses a mishmash of named int constants instead, e.g. Calendar. Unfortunately, these have no type safety, and they are not organised into functional groups. enums are used in some of the more recent classes such as java.util.concurrent. TimeUnit and java.lang.annotation. ElementType.

General Purpose enum Code

Writing general purpose code to work an arbitrary enums is quite tricky. You need to use generics deftly and play with class objects. Part of the problem is passed parameters cannot access the static methods of the enum as a whole. Here is an example that will select a random enum constant from an arbitrary 

Learning More

Oracle’s Technote Guide on enums : available:
Oracle’s Javadoc on Enum, the class underpinning enums : available:
Oracle’s Javadoc on EnumMap class : available:
Oracle’s Javadoc on Class.getEnumConstants : available:
Oracle’s JDK Platform Guide to serializing enums : available:
Oracle’s Javadoc on serialization form for enum : available:
Oracle’s Javadoc on Class.getEnumConstants : available:
Oracle’s Javadoc on EnumMap class : available:

To Come

inner class gotchas

This page is posted
on the web at:

http://mindprod.com/jgloss/enum.html

Optional Replicator mirror
of mindprod.com
on local hard disk J:

J:\mindprod\jgloss\enum.html
logo
Please the feedback from other visitors, or your own feedback about the site.
Contact Roedy. Please feel free to link to this page without explicit permission.
Blog
IP:[65.110.21.43]
Your face IP:[184.73.85.45]
You are visitor number