Should you always use enums instead of constants in Java

19,157

Solution 1

Don't know about Java, but in .NET the good practice is to put enums in parallel to the class that uses them, even if it is used by one class alone. That is, you would write:

namespace Whatever
{
    enum MyEnum
    {
    }
    class MyClass
    {
    }
}

Thus, you can use:

MyClass c = new MyClass(MyEnum.MyValue);

Solution 2

You complicated it too much. Let's bring it all together.

Post Java 1.5 you should use the Java Enum class:

public enum Color
{
    BLACK, WHITE;
}

Pre Java 1.5 you should use the type-safe Enum pattern:

public class Color
{
    public static Color WHITE = new Color("white");
    public static Color BLACK = new Color("black");

    private String color;

    private Color(String s)
    {
        color = s;
    }
}

In both ways you call it like so:

drawBackground(Color.WHITE);

Specifically, regarding your question. It's a matter of code style, but I think the preferred way is to keep enums in their separate classes. Especially once they start to get their own methods like getName(), getId(), etc... Think of it as the same dilemma as regular class vs. anonymous class, once the class starts to get cluttered, it's time to move it out to its own file.

Solution 3

Did you know you can import Orientation and say

MyClass myClass = new MyClass(Orientation.VERTICAL);

?

Solution 4

There is an important class of cases where you should use constants instead of enums. This is when you want to do arithmetic using the constants, or compare them with numeric values. Then you really need the thing to be an int, long or double.

Conversely, if it would never make sense to do arithmetic or numerical comparisons using a thing, that thing should be an object rather than a primitive numeric, so an enum would be more appropriate.

Share:
19,157
Draemon
Author by

Draemon

I am a software developer with a CS background. While my background in CS has armed me with the techniques, algorithms and tools to do my job; creating useful software for a real business requires a greater knowledge of both the problem domain and effective working practices than of the latest and greatest algorithms. I'm very much into learning things from the ground up. I think that learning assembly language and C has made me a much better programmer. Follow me on twitter CV Linked In

Updated on June 05, 2022

Comments

  • Draemon
    Draemon about 2 years

    In java <1.5, constants would be implemented like this

    public class MyClass {
        public static int VERTICAL = 0;
        public static int HORIZONTAL = 1;
    
        private int orientation;
    
        public MyClass(int orientation) {
            this.orientation = orientation;
        }
    ...
    

    and you would use it like this:

    MyClass myClass = new MyClass(MyClass.VERTICAL);
    

    Now, in 1.5 obviously you should be using enums:

    public class MyClass {
        public static enum Orientation {
            VERTICAL, HORIZONTAL;
        }
    
        private Orientation orientation;
    
        public MyClass(Orientation orientation) {
            this.orientation = orientation;
        }
    ...
    

    and now you would use it like this:

    MyClass myClass = new MyClass(MyClass.Orientation.VERTICAL);
    

    Which I find slightly ugly. Now I could easily add a couple of static variables:

    public class MyClass {
        public static Orientation VERTICAL = Orientation.VERTICAL;
        public static Orientation HORIZONTAL = Orientation.HORIZONTAL;
    
        public static enum Orientation {
            VERTICAL, HORIZONTAL;
        }
    
        private Orientation orientation;
    
        public MyClass(Orientation orientation) {
            this.orientation = orientation;
        }
    ...
    

    And now I can do this again:

    MyClass myClass = new MyClass(MyClass.VERTICAL);
    

    With all the type-safe goodness of enums.

    Is this good style, bad style or neither. Can you think of a better solution?

    Update

    Vilx- was the first one to highlight what I feel I was missing - that the enum should be a first-class citizen. In java this means it gets its own file in the package - we don't have namespaces. I had thought this would be a bit heavyweight, but having actually done it, it definitely feels right.

    Yuval's answer is fine, but it didn't really emphasise the non-nested enum. Also, as for 1.4 - there are plenty of places in the JDK that use integers, and I was really looking for a way to evolve that sort of code.

    • Nate Parsons
      Nate Parsons over 15 years
      In the first code block, you meant to give each variable a different value, right?
    • Pål GD
      Pål GD over 15 years
      Do you actually need the class MyClass to do more than just the different Orientations could do?
  • Draemon
    Draemon over 15 years
    Good point. Yes I did, but that still means more verbosity in the calling code (it adds an import line). My motivation is to keep the calling code shorter and cleaner.
  • Yoni Roit
    Yoni Roit over 15 years
    I'm, sorry, man. I mean, I love Java and all, but shorter has never been a priority in this language.
  • Yoni Roit
    Yoni Roit over 15 years
    You have a point, but using enum is a bit more self-describing then just a boolean.
  • Draemon
    Draemon over 15 years
    I agree that I've just shifted the ugliness, but I always slightly prefer it being in called code as opposed to calling code. It's absolutely personal, and I'm not even sure I like the alternative, which is why I'm asking for perspectives. I'm coming to the conclusion a separate class would be best.
  • Nate Parsons
    Nate Parsons over 15 years
    but if you're just passing it into a function, then you can make the signature 'public MyClass(boolean isVertical)'. That's about the only case I would use it, though.