Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Create enumerated constants in Java

The weaknesses of Java's static finals are defined here and a template is provided for creating typesafe constants

  • Print
  • Feedback

Page 2 of 6

But static finals are risky
Still, there are a couple of drawbacks to using static final integers. The major drawback is the lack of type safety. Any integer that is calculated or read in can be used as a "color," regardless of whether it makes sense to do so. You can loop right past the end of the defined constants or stop short of covering them all, which can easily happen if you add or remove a constant from the list but forget to adjust the loop index.

For example, your color-preference loop might read like this:

  for (int i=0; i <= BLUE; i++) {
    if (customerLikesColor(i)) {
       favoriteColors.add(i);
    }
  }


Later on, you might add a new color:

  static final int RED = 0;
  static final int GREEN = 1;
  static final int BLUE = 2;
  static final int MAGENTA = 3;


Or you might remove one:

  static final int RED = 0;
  static final int BLUE = 1;


In either case, the program will not operate correctly. If you remove a color, you will get a runtime error that draws attention to the problem. If you add a color, you won't get any error at all -- the program will simply fail to cover all of the color choices.

Another drawback is the lack of a readable identifier. If you use a message box or console output to display the current color choice, you get a number. That makes debugging pretty difficult.

The problems creating a readable identifier are sometimes solved using static final string constants, like this:

  static final String RED = "red".intern();
  ...


Using the intern() method guarantees there is only one string with those contents in the internal string pool. But for intern() to be effective, every string or string variable that is ever compared to RED must use it. Even then, static final strings do not allow for looping or for indexing into an array, and they still do not address the issue of type safety.

Type safety

The problem with static final integers is that the variables that use them are inherently unbounded. They are int variables, which means they can hold any integer, not just the constants they were intended to hold. The goal is to define a variable of type Color so that you get a compilation error rather than a runtime error whenever an invalid value is assigned to that variable.

An elegant solution was provided in Philip Bishop's article in JavaWorld, "Typesafe constants in C++ and Java."

The idea is really simple (once you see it!):

  public final class Color {   // final class!!
    private Color() {}         // private constructor!!

public static final Color RED = new Color(); public static final Color GREEN = new Color(); public static final Color BLUE = new Color(); }


Because the class is defined as final, it can't be subclassed. No other classes will be created from it. Because the constructor is private, other methods can't use the class to create new objects. The only objects that will ever be created with this class are the static objects the class creates for itself the first time the class is referenced! This implementation is a variation of the Singleton pattern that limits the class to a predefined number of instances. You can use this pattern to create exactly one class any time you need a Singleton, or use it as shown here to create a fixed number of instances. (The Singleton pattern is defined in the book Design Patterns: Elements of Reusable Object-Oriented Software by Gamma, Helm, Johnson, and Vlissides, Addison-Wesley, 1995. See the Resources section for a link to this book.)

  • Print
  • Feedback

Resources