Search code examples
javaenumsfinal

When should I use the final keyword instead of enums?


I had the following field in my code:

private static final int NUM_NANOSECONDS_IN_MILLISECOND = 1000000;

I was told that I should be using an enum for this for type safety. This is not something I am familiar with. But if this is the case, I don't know when it would ever be appropriate to use the final keyword on a field.

When should I use the final keyword instead of enums?


Solution

  • Constants are just that, constants with a name. Enums are literal constants that have a value. I explain...

    Consider:

    public final static int NORTH = 0;
    public final static int SOUTH = 1;
    public final static int EAST = 2;
    public final static int WEST = 3;
    

    and

    public enum Direction {
        NORTH, SOUTH, EAST, WEST
    }
    

    From a readability standpoint it kinda looks the same:

    if(direction == NORTH)
    

    or with enums:

    if(direction == Direction.NORTH)
    

    Where things might go wrong is that with the final constant, you can also do

    if(direction == 0)
    

    Now it's more difficult to understand the code even though it does the same thing. With enums, you just can't do that so it's let problems.

    Similarly, when expecting a direction as a method argument:

    with final static:

    public void myMethod(int direction)
    

    and with enums:

    public void myMethod(Direction direction)
    

    It's clearer, and less opportunities for problems.

    This is just a beginning. Enums can actually have methods that help you better manage the information they contain. Read up here for a clean explanation.

    Example:

    public enum Direction {
        NORTH (0, 1),
        SOUTH (0, -1),
        EAST (1, 0),
        WEST (-1, 0)
    
        private int xDirection, yDirection;
    
        Direction(int x, int y) {
            this.xDirection = x;
            this.yDirection = y;
        }
    
        public Vector2D getTranslation() {
            return new Vector2D(this.xDirection, this.yDirection);
        }
    }
    

    So then in your code:

    public void moveThePlayer(Player p, Direction d) {
        p.translate(d.getTranslation());
    }
    
    moveThePlayer(p, Direction.NORTH);
    

    This becomes really hard to do with final static. Or at least, it gets very unreadable.

    All this being said, with the particular case you are working with there, if there's only one numeric constant value, I'd keep the final static. No point using an enum if there's a single value.