Java Notes
Enums
Problem: How to represent a set of named constant values. First we'll look at the "old" Java solution, then see how Java 5 enums substantially improve the situation.
Older, but common, solution
Just define a number of public static final int constants. For example:
//... Constants to represent possible shapes. public static final int RECTANGLE = 0; public static final int CIRCLE = 1; public static final int LINE = 2; ... int drawing = RECTANGLE; // But any int could be assigned.
These values can then be assigned to an integer variable, and can be used in switch statements. This style is useful, but is not a great solution.
- Allows illegal values. Any variable containing one of these values could
also be assigned any integer value, although there are only three
legal choices. Eg,
drawing = 99; // Illogical value, but allowed by compiler.
- Updates not reflected in other code. If there are additions, deletions, or reorderings, code from other classes will not automatically be readjusted to reflect these changes. All code that uses these definitions would have to be recompiled.
- No easy I/O. To convert values to and from a string form requires maintaining an additional array and lookup code.
- Fragile for loops. There is no obvious first and last value so iterating over all values is subject to errors which are not diagnosed at compile time if the values are rearranged, deleted, or added to. There is no way to use the enhanced for loop.
- No behavior. This style is pre-OOP -- there are values, but no behavior defined for them.
Defining an enum type
An enum type is a kind of class definition. The possible enum values are listed in the curly braces, separated by commas. By convention the value names are in upper case.
public enum Shape { RECTANGLE, CIRCLE, LINE }
Declaring enum variables and using enum values
The enum class name can be use like any other class type in declarations. Usually enum values must be prefixed with the enum type name.
Shape drawing = Shape.RECTANGLE; // Only a Shape value can be assigned.
Printing enum values
The enum class has a toString()
method defined that returns
the unqualified string version of the value. This means that it's easy to print these
values without any special conversion effort.
System.out.println(drawing); // Prints RECTANGLE
Looping over all enum values with foreach loop
The static values()
method of an enum type returns
an array of the enum values. The foreach loop is a good
way to go over all of them.
//... Loop over all values. for (Shape shp : Shape.values()) { System.out.println(shp); // Prints RECTANGLE, CIRCLE, ... }
Switch statement
The switch
statement was enhanced to allow a convenient use
of enums. Note that the case values don't have to be qualified with the
enum class name, which can be determined from the switch
control value.
switch (drawing) { case RECTANGLE: g.drawRect(x, y, width, height); break; case CIRCLE : g.drawOval(x, y, width, height); break; case LINE : g.drawLine(x, y, x + width, y + height); break; }
Getting an integer equivalent of an enum value
Each enum value in an enum class has an associated default value,
starting with zero for the first value and incrementing by one for each
additional value. This may be accessed with the ordinal()
method.
System.out.println(drawing.ordinal()); // Prints 0 for RECTANGLE.
Input
The valueOf()
method can be used to convert a string value
to an enum value. Here is an example of reading in a Shape value from
a Scanner object in.
drawing = Shape.valueOf(in.next());
Defining additional fields, methods, and constants for your enum type
Methods can be defined for an enum class, including defining a different method body for each of the constants. See the Sun article for examples of this. If you are using switch statements with cases for each of the enum constants, consider putting the code into the enum class.
Related data structure classes: EnumSet and EnumMap
The java.util.EnumSet class provides an efficient implementation of sets of enums as bit maps, or powersets as they were called in Pascal. EnumSet can also generate an Iterable for use with subsets in the for-each statement.
java.util.EnumMap provides an efficient implementation of a map for enums based on an array.
Further reading
- Enums is a good Sun overview of the Java enum features. It's very readable with good examples.
- Example: PaintDemo is a small paint program which represents the shape with an enum. It shows how to use an enum to represent simple constants, and also how to associate a method with each constant.
- Class Enum<E extends Enum<E>>
is the API documentation for the superclass of all enums.
You'll find useful methods in this class such as
compareTo(...)
,ordinal()
,toString()
, andvalueOf(...)
. The addition of generics negated the former Java claim to simplicity, and it's this Enum definition which is often used as an example of the incomprehensible. It's hard to find anyone who understands this obscure declaration. Fortunately, the use of enums doesn't require that that you know what this declaration means. - Java language - Enum Switch discusses proposals for making enums in switch statements more robust.