Why Enumerate a Type?

Here's the older approach of simulating enumerations:

class Bread {
    static final int wholewheat = 0;
    static final int ninegrain = 1;
    static final int rye = 2;
    static final int french = 3;
}

You would then declare an int variable and let it hold values from the Bread class, e.g.

int todaysLoaf = Bread.rye;

Drawbacks of using ints to enumerate

Using final ints to represent values in an enumeration has at least three drawbacks.

  • All the compiler tools (debugger, linker, run-time, etc.) still regard the variables as ints. They are ints. If you ask for the value of todaysLoaf, it will be 2, not “rye”. The programmer has to do the mapping back and forth mentally.

  • The variables aren't typesafe. There's nothing to stop todaysLoaf getting assigned a value of 99 that doesn't correspond to any Bread value. What happens next depends on how well the rest of your code is written, but the best case is that some routine notices pretty quickly and throws an exception. The worst case is that your computer-controlled bakery tries to bake “type 99” bread causing an expensive sticky mess.

  • Use of integer constants makes code “brittle” (easily subject to breakage). The constants get compiled into every class that use them. If you update the class where the constants are defined, you must go and find all the users of that class, and recompile them against the new definitions. If you miss one, the code will run but be subject to subtle bugs.

How enums solve these issues

Enumerated types were introduced with JDK 1.5 to address these limitations. Variables of enumerated types

  • Are displayed to the programmer or user as Strings, not numbers

  • Can only hold values defined in the type

  • Do not require clients to be recompiled when the enumeration changes

Enumerated types are written using a similar syntax to class declarations, and you should think of them as being a specialized sort of class. An enumerated type definition can go in a file of its own, or in a file with other classes. A public enumeration must be in a file of its own with the name matching the enumeration name.

You might create an enumerated type to represent some bread flavors. It would be defined like this:

enum Bread { wholewheat, ninegrain, rye, french }

That lets you declare variables of type Bread in the usual way:

Bread todaysLoaf;

You can assign an enum value to a variable of Bread type like this:

todaysLoaf = Bread.rye;

All the language tools know about the symbolic names. If you print out a Bread variable, you get the string value, not whatever numeric constant underlies it internally.

System.out.println("bread choice is: " + todaysLoaf);

This results in output of:

bread choice is: rye

How enums are implemented

Under the covers, enum constants are static final objects declared (by the compiler) in their enum class. An enum class can have constructors, methods, and data. Enum variables are merely pointers to one of the static final enum constant objects.

You'll understand enums better if you know that the compiler treats them approximately the same way as if it had seen this source code:

class Bread extends Enum {
   // constructor
   public Bread(String name, int position) { super(name, position); }

   public static final Bread wholewheat = new Bread("wholewheat",0);
   public static final Bread ninegrain = new Bread("ninegrain", 1);
   public static final Bread rye = new Bread("rye", 2);
   public static final Bread french = new Bread("french", 3);

   // more stuff here
}

This is an approximation because the parent class, java.lang.Enum, uses a generic parameter, and we cover generics later. Bringing generics into the definition of Enum was an unnecessary complication aimed at improving the type-safety of enums. The work could and should have been moved into the compiler. The previous code should give you a good idea of how enums are represented.

Enum constants make software more reliable

Here's an amazing thing: the constants that represent the enumeration values are not compiled into other classes that use the enumeration. Instead, each enum constant (like Bread.rye previously) is left as a symbolic reference that will be linked in at run-time, just like a field or method reference.

If you compile a class that uses Bread.rye, and then later add some other bread flavors at the beginning of the enumeration (pumpernickel and oatmeal), Bread.rye will now have a different numeric value. But you do not need to recompile any classes that use the enumeration. Even better, if you remove an enum constant that is actually being used by some other class (and you forget to recompile the class where it's used), the run-time library will issue an informative error message as soon as you use the now-removed name. This is a significant boost to making Java software more reliable.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.12.232