tags:

views:

202

answers:

9

I'm looking at some Java code that are maintained by other parts of the company, incidentally some former C and C++ devs. One thing that is ubiquitous is the use of static integer constants, such as

class Engine {
    private static int ENGINE_IDLE = 0;
    private static int ENGINE_COLLECTING = 1;
    ...
}

Besides a lacking 'final' qualifier, I'm a bit bothered by this kind of code. What I would have liked to see, being trained primarily in Java from school, would be something more like

class Engine {
    private enum State { Idle, Collecting };
    ...
}

However, the arguments fail me. Why, if at all, is the latter better than the former?

+5  A: 

Because enums provide type safety. In the first case, you can pass any integer and if you use enum you are restricted to Idle and Collecting.

FYI : http://www.javapractices.com/topic/TopicAction.do?Id=1.

fastcodejava
A: 

The former is common in code that started pre-1.5. Actually, another common idiom was to define your constants in an interface, because they didn't have any code.

Paul Tomblin
But that practice also encourages the use of inheriting those constants, which is a bit ugly. :(
David Grant
@David: it's the least of the problems that "integer constant enums" cause.
Michael Borgwardt
@Michael: But a problem none the less.
David Grant
@David, yes, and that's why they also introduced "import static" after 1.5.
Paul Tomblin
+5  A: 

By using an int to refer to a constant, you're not forcing someone to actually use that constant. So, for example, you might have a method which takes an engine state, to which someone might happy invoke with:

engine.updateState(1);

Using an enum forces the user to stick with the explanatory label, so it is more legible.

David Grant
+15  A: 

Why, if at all, is the latter better than the former?

It is much better because it gives you type safety and is self-documenting. With integer constants, you have to look at the API doc to find out what values are valid, and nothing prevents you from using invalid values (or, perhaps worse, integer constants that are completely unrelated). With Enums, the method signature tells you directly what values are valid (IDE autocompletion will work) and it's impossible to use an invalid value.

The "integer constant enums" pattern is unfortunately very common, even in the Java Standard API (and widely copied from there) because Java did not have Enums prior to Java 5.

Michael Borgwardt
+1 because you are the only one mentioning self-documentation. If you have an method, that accepts (or returns) an int, that represents some code, you have without doc or source no chance to conclude to the semantics of the int. But the enum has a name for each value and the signature is directly (via type) connected to the enum.
Mnementh
+1 for "self-documenting" and "IDE autocompletion will work"
Yatendra Goel
+1  A: 

There is one situation when static constance is preferred (rather that the code is legacy with tonne of dependency) and that is when the member of that value are not/may later not be finite.

Imagine if you may later add new state like Collected. The only way to do it with enum is to edit the original code which can be problem if the modification is done when there are already a lot of code manipulating it. Other than this, I personally see no reason why enum is not used.

Just my thought.

NawaMan
However, adding a new state would probably require other changes in the code (meaning handling of that new state). So the scenario is not very likely. Legacy code is probably the only place where this approach is appropriate.
Lajcik
+1  A: 
  1. Readabiliy - When you use enums and do State.Idle, the reader immediately knows that you are talking about an idle state. Compare this with 4 or 5.

  2. Type Safety - When use enum, even by mistake the user cannot pass a wrong value, as compiler will force him to use one of the pre-declared values in the enum. In case of simple integers, he could even pass -3274.

  3. Maintainability - If you wanted to add a new state Waiting, then it would be very easy to add new state by adding a constant Waiting in your enum State without casuing any confusion.
Suraj Chandran
+5  A: 

An excerpt from the official docs, http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html:

This pattern has many problems, such as:

  • Not typesafe - Since a season is just an int you can pass in any other int value where a season is required, or add two seasons together (which makes no sense).
  • No namespace - You must prefix constants of an int enum with a string (in this case SEASON_) to avoid collisions with other int enum types.
  • Brittleness - Because int enums are compile-time constants, they are compiled into clients that use them. If a new constant is added between two existing constants or the order is changed, clients must be recompiled. If they are not, they will still run, but their behavior will be undefined.
  • Printed values are uninformative - Because they are just ints, if you print one out all you get is a number, which tells you nothing about what it represents, or even what type it is.

And this just about covers it. A one word argument would be that enums are just more readable and informative.

One more thing is that enums, like classes. can have fields and methods. This gives you the option to encompass some additional information about each type of state in the enum itself.

Lajcik
A: 

Enums also give you a great deal of flexibility. Since Enums are essentially classes, you can augment them with useful methods (such as providing an internationalized resource string corresponding to a certain value in the enumeration, converting back and forth between instances of the enum type and other representations that may be required, etc.)

VoidPointer
A: 

The reasons from the spec, which Lajcik quotes, are explained in more detail in Josh Bloch's Effective Java, Item 30. If you have access to that book, I'd recommend perusing it. Java Enums are full-fledged classes which is why you get compile-time type safety. You can also give them behavior, giving you better encapsulation.

Rob Thornton