Java 1.5 Tiger A Developers Notebook [Electronic resources]

David Flanagan, Brett McLaughlin

نسخه متنی -صفحه : 131/ 41
نمايش فراداده

3.5 Maps of Enums

Once you've gotten your fingers used to typing public enum, you'll start to find all sorts of interesting uses for enums. Once you've gotten past the very basic constant-replacement, you'll start to see that they also serve as great keys, or indices, in collection-type structures. Apparently the Sun guys thought the same thing, and provided a nice facility for working with enums as indices.

3.5.1 How do I do that?

In the old, archaic, pre-Tiger days (snicker, snicker), you might have used a constants class like OldAntStatus (you'll remember a similar class from Example 3-3):

public class OldAntStatus {
public static final int INITIALIZING = 0;
public static final int COMPILING    = 1;
public static final int COPYING      = 2;
public static final int JARRING      = 3;
public static final int ZIPPING      = 4;
public static final int DONE         = 5;
public static final int ERROR        = 6;
}

You might then write a simple array of messages that are associated with each of these status codes:

String[] antMessages = new String[] {
"Initalizing Ant...",        // INITIALIZING
"Compiling Java classes...", // COMPILING
"Copying files...",          // COPYING
"JARring up files...",       // JARRING
"ZIPping up files...",       // ZIPPING
"Build complete.",           // DONE
"Error occurred."            // ERROR
}

You can then access the appropriate message using the constant:

int antStatus = antProcess.getStatus( );
out.println("ant> " + antMessages[antStatus]);

It's a pretty valid desire to want to accomplish the same sorts of tasks with enumerated types, and get all the benefits of enums along the way. You'll need to use the java.util.EnumMap class to accomplish this, which is a new collection type just perfect for the job. First, you need to define the enum you want to use for a keyset, as shown in Example 3-4.

Example 3-4. An enum to use for a keyset
package com.oreilly.tiger.ch03;
public enum AntStatus {
INITIALIZING,
COMPILING,
COPYING,
JARRING,
ZIPPING,
DONE,
ERROR
}

You can now create a new EnumMap, in conjunction with generics declare the enumerated type you want to use for the key, and the class type you want to use for the value:

EnumMap<AntStatus, String> antMessages;

Then, when creating a new instance, you pass the EnumMap the Class object for the enum used for the keyset:

EnumMap<AntStatus, String> antMessages =
EnumMap<AntStatus, String>(AntStatus.class);

This should further emphasize the fact that enums are really just Java classes that the compiler handles specially. This is discussed in more detail in Creating an Enum lab.

NOTE

Remember to declare the types being used, key and value, in both the variable declaration and the variable instantiation.

Once the initialization is taken care of, things get very simple. You just seed the values, and use them:

public void testEnumMap(PrintStream out) throws IOException {
// Create a map with the key and a String message
EnumMap<AntStatus, String> antMessages =
new EnumMap<AntStatus, String>(AntStatus.class);
// Initialize the map
antMessages.put(AntStatus.INITIALIZING, "Initializing Ant...");
antMessages.put(AntStatus.COMPILING,    "Compiling Java classes...");
antMessages.put(AntStatus.COPYING,      "Copying files...");
antMessages.put(AntStatus.JARRING,      "JARring up files...");
antMessages.put(AntStatus.ZIPPING,      "ZIPping up files...");
antMessages.put(AntStatus.DONE,         "Build complete.");
antMessages.put(AntStatus.ERROR,        "Error occurred.");
// Iterate and print messages
for (AntStatus status : AntStatus.values( ) ) {
out.println("For status " + status + ", message is: " +
antMessages.get(status));
}
}

NOTE

This code is in AntStatusTester. java.

Running this code nicely prints out all the status codes, and the associated message with each:

[echo] Running AntStatusTester...
[java] For status INITIALIZING, message is: Initializing Ant...
[java] For status COMPILING, message is: Compiling Java classes...
[java] For status COPYING, message is: Copying files...
[java] For status JARRING, message is: JARring up files...
[java] For status ZIPPING, message is: ZIPping up files...
[java] For status DONE, message is: Build complete.
[java] For status ERROR, message is: Error occurred.

Of course, as an added benefit, EnumMap protects you from mis-ordering when initializing values, reordering in the enumerated type, and just about any other strange situation that can arise from more than one person working on code at the same time.