Advertisement
Guest User

Making the Most of Java 5.0: Enum Tricks

a guest
Feb 22nd, 2013
1,179
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.74 KB | None | 0 0
  1. Making the Most of Java 5.0: Enum Tricks
  2. By Brennan Spies - Posted on December 6th, 2007
  3. Tagged:
  4.  
  5. Java
  6.  
  7. So your organization has finally moved to Java 5.0...and you are wondering what you can do with some of its new features. In this first of a series of articles on Java 5.0, I'll show you some of the interesting ways that you can exploit the new language features to improve the way you code Java.
  8.  
  9. First off, enumerations.
  10.  
  11. Introduction to Enums
  12.  
  13. The enumeration is a way of creating self-documenting code, a big improvement over the "magic" integer or string constants which are often used to represent a defined set of values. Enumerations abound in object models, and examples are not hard to find: days of the week, colors, card suits, etc. The idea of enumerations as an actual programming language type goes back to Pascal. Many programmers, though, are likely to be more familiar with the C/C++ version of it as the enum, which is just a decorated integer:
  14.  
  15. //use optional assignment to ints to illustrate
  16. enum suit {
  17. SPADES = 1,
  18. HEARTS = 2,
  19. DIAMONDS = 3,
  20. CLUBS = 4
  21. };
  22.  
  23. Figure 1: C/C++ enum
  24.  
  25. Enums in Java
  26.  
  27. In Java, the introduction of enumerations started informally with Joshua Bloch's type-safe enumeration pattern. The pattern boils down to essentially this: a Java class with a private constructor that declares public static final versions of itself.
  28.  
  29. public final class Suit {
  30. private Suit() {}
  31. public static final Suit SPADES = new Suit();
  32. public static final Suit HEARTS = new Suit();
  33. public static final Suit DIAMONDS = new Suit();
  34. public static final Suit CLUBS = new Suit();
  35. }
  36.  
  37. Figure 2: The type-safe enumeration pattern
  38.  
  39. The advantage of this style of enumeration over the C/C++-style enum or constants is that they are "type-safe", meaning that, for example, if you define a method
  40.  
  41. public void setSuit(Suit suit) { ... }
  42.  
  43. the caller cannot pass in a value that does not correspond to an enumeration value. With a constant or C/C++-style enum, you could pass in a random value (like -1) that would not. Java-style enumerations have the additional advantage that, since they are classes, you can "associate" other data with them. This idea will be illustrated a little later. Since these enumeration instances are all effectively singletons, they can be compared for equality using identity ("==").
  44.  
  45. Enums in Java 5.0
  46.  
  47. In Java 5.0, the enum keyword is introduced as a special type of class that always extends java.lang.Enum. These closely resemble an abbreviated version of Bloch's type-safe enumeration pattern.
  48.  
  49. public enum Suit {
  50. SPADES,
  51. HEARTS,
  52. DIAMONDS,
  53. CLUBS //optionally can end with ";"
  54. }
  55.  
  56. Figure 3: The Java 5.0 enum
  57.  
  58. The difference is that this version includes utility methods like name() that returns the declared variable name as a String, ordinal() that returns the position of the enum as it is declared in the class, and valueOf() which allows you to look up the enum using its declared variable name as a String. Java 5.0 enumerations also can be used in switch statements, a nice convenience. Note that the enumeration values are still static class members, though not declared as such.
  59.  
  60. So, going beyond the basics, what can you do with Java enumerations? Here are a few handy tricks...
  61.  
  62. Enums and Template Methods
  63.  
  64. Remember that the enum is basically a special class type, and can have methods and fields just like any other class. Remember also that each declared field is also an instance of the enum. So, applying the "Template Method" design pattern, one can create enumerations that are factories or command objects, but a defined set of objects. Here is a simple example of a "command" enumeration:
  65.  
  66. public enum Toy {
  67. DOLL() {
  68. @Override public void execute() {
  69. System.out.println("I'm a doll.");
  70. }
  71. },
  72. SOLDIER() {
  73. @Override public void execute() {
  74. System.out.println("I'm a soldier.");
  75. }
  76. };
  77. //template method
  78. public abstract void execute();
  79. }
  80.  
  81. Figure 4: The enum with template method
  82.  
  83. With the use of static imports, the client code calling this enumeration would look like:
  84.  
  85. SOLDIER.execute();
  86. DOLL.execute();
  87. //or better...
  88. getToy().execute();
  89.  
  90. The resulting code is clear and self-documenting. Using this pattern is a great alternative in many cases to the more common if(toy=="soldier"){...} else if(toy=="doll"){...} else{...} logic since it is easier to read, extend, and maintain.
  91.  
  92. Reverse Lookups
  93.  
  94. Often in your object model it is common to have data that is naturally "associated" with an enumeration. Since an enum is a class, it is easy to represent this associated information as class fields. Often it is desirable to "lookup" the associated enumeration using the field value. This is easy to do using a static java.util.Map. Take, for example, a Status enum that has an associated status code.
  95.  
  96. public enum Status
  97. {
  98. WAITING(0),
  99. READY(1),
  100. SKIPPED(-1),
  101. COMPLETED(5);
  102.  
  103. private static final Map<Integer,Status> lookup
  104. = new HashMap<Integer,Status>();
  105.  
  106. static {
  107. for(Status s : EnumSet.allOf(Status.class))
  108. lookup.put(s.getCode(), s);
  109. }
  110.  
  111. private int code;
  112.  
  113. private Status(int code) {
  114. this.code = code;
  115. }
  116.  
  117. public int getCode() { return code; }
  118.  
  119. public static Status get(int code) {
  120. return lookup.get(code);
  121. }
  122. }
  123.  
  124. Figure 5: The enum reverse lookup
  125.  
  126. The static get(int) method here provides the reverse lookup by simply getting the value from the Map. The static block to populate the Map uses a specialized implementation of Set, java.util.EnumSet, that "probably" (according to the javadocs) has better performance than java.util.HashSet. Java 5.0 also provides java.util.EnumMap, a specialized implementation of Map for enumerations that is more compact than java.util.HashMap.
  127.  
  128. Conclusion
  129.  
  130. The enum in Java 5.0 represents a cleaner, more self-documenting, richer, and in many cases, more efficient way of coding certain object model concepts than was possible using the older idiom of static final constants. Even if you are still using Java 1.4.x or earlier, you can still gain many of the benefits of the enum by using the type-safe enumeration pattern; this will also make the code easier to migrate once you do go to Java 5.0. Older client code that uses constants can still be adapted to use the enum by associating constant values with the enumerations themselves (as seen in the Status class, Figure 5). So, in other words, there is no reason not to convert your old static constants to enumerations. The guy who has to maintain your code will thank you.
  131.  
  132. Update: there's a second part to this article here.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement