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

Constants, I do declare

Readers describe how they employ constants

  • Print
  • Feedback

In "Constants" (JavaWorld, March 30, 2001), I wrote, "I'd be interested to hear how others declare their constants and why. I can post your responses in a future Q&A." Well, here are some reader responses.

It turns out that using an interface to declare constants may not be the best practice after all. In fact, using interfaces in this way may be downright nasty. Why? Interfaces should only be used to define types; any other use is an abuse. Using an interface causes internal details -- such as constants -- to leak into the class' public API. Once something becomes part of the public API, you can never get rid of it. Thanks to Josh Bloch for smacking me upside the head and setting me straight.

Josh pointed me to his excellent article, "Substitutes for Missing C Constructs," (java.sun.com), which describes a design pattern for creating design patterns in Java. Such a pattern works very nicely for declaring XML tags. Be sure to look out for Josh's upcoming book, Effective Java Programming Language Guide (Addison-Wesley, June 2001).

Originally, I advocated using an interface. Consider the following XML markup:.

<Recipes>
   <Recipe>
      <Ingredient>
      <Ingredient>
   </Recipe>
</Recipes>


I would have created the following interface:

public interface RecipeMarkup {
   public final static String RECIPES_TAG    = "Recipes";
   public final static String RECIPE_TAG     = "Recipe";
   public final static String INGREDIENT_TAG = "Ingredient";
}


By following the pattern, I can create the following class instead:

public class Markup {
   private final String tag;
// make protected so we can override if new tags are added
   protected Markup(String tag) { this.tag = tag; }
public String toString()  { return tag; }
   // might also add a compare(String) method to simplify comparison
   // such as when we want to handle SAX events
   
   public static final Markup RECIPES =
      new Markup("Recipes");
   public static final Markup RECIPE =
      new Markup("Recipe");
   public static final Markup INGREDIENT =
      new Ingredient("Ingredient");
}


By adding a compare(String) method, we can simplify tag comparison. For example, if you use SAX, you have to do a string comparison to figure out what tag you're dealing with in the event. This pattern is great for enumerations; the XML markup should be an enum. However, there are some other ways to define pure run-of-the-mill constants.

Jay Baker sent me a good suggestion. I'll let him say it in his own words:

I prefer the use of an abstract class with public static final constants for most implementations. This is just as easy to implement. Whether an interface or a class, one must still define the interface or class and put the constants in there. The best reason to use this method is that it more closely matches the design concept. Using an abstract class is an implementation of the "uses" association that is really what you want with constants. Implementing an interface implies something that is not really there in the case of constants.


Josh Bloch made a similar suggestion:

I'd still recommend against the use of "constant interfaces." Interfaces should be used to define types; any other use constitutes abuse. If the constants are subservient to some other class or interface, put them into it. If not, make a "utility class" containing the constants:

public class RecipeMarkup {
    private RecipeMarkup() { } // Prevents instantiation
    public static final String RECIPES_TAG    = "Recipes";
    public static final String RECIPE_TAG     = "Recipe";
    public static final String INGREDIENT_TAG = "Ingredient";
}


Note that I've done three things to your interface: First, I turned it into a class. Second, I added a private constructor to suppress the default constructor, thus guaranteeing noninstantiability. Third, I made all the constants final. Your constants weren't final, so a malicious or confused client could change them.