19

I've found Enums defined like the following:

public Enum MyEnum {

   ONE
   {
      @Override
      public int getSomething() {
         return 1;
      } 
   },

   TWO
   {
      @Override
      public int getSomething() {
        return 2;
      }
   }

   int getSomething()
   {
      return 0;
   }
}

Somehow I feel some type of discomfort with this implementation because I would think that ideally a field should be defined for this purpose and the class should look something like:

public Enum MyEnum{

   ONE(1),
   TWO(2)

   private int theSomething;

   private MyEnum(int something) {
      theSomething = something;
   }

   int getSomething()
   {
      return theSomething;
   }
}

The problem is that apart from personal discomfort I cannot find any good reason to change this code. Do any exists?

David Newcomb
  • 10,639
  • 3
  • 49
  • 62
Sednus
  • 2,095
  • 1
  • 18
  • 35
  • 1
    The second form makes it more readable and more extendable, go for that one! – Tom Feb 19 '13 at 21:49
  • 1
    It's a *state machine* in your first example. Not implemented quite right (`getSomething()` should be abstract ) ... but that's why you use that type of structure. And the methods are generally far more complex in a real example (they actually do things rather than returning static values) and/or throw `IllegalStateException` when they shouldn't be called in a current state. – Brian Roach Feb 19 '13 at 21:49
  • 1
    Both of these are valid approaches. – Louis Wasserman Feb 19 '13 at 22:03

2 Answers2

28

(moved from comment)

Your first example is used commonly to implement a finite state machine in Java. It eliminates the need for every method having to have a if (state == FOO) {} else if (state == BAR) etc

class MyFSM {

    enum State {
        FIRST_STATE {
            @Override
            void start(MyFSM fsm) {
                fsm.doStart();
            }
            @Override
            void stop(MyFSM fsm) {
                throw new IllegalStateException("Not Started!");
            }
        },
        SECOND_STATE {
            @Override
            void start(MyFSM fsm) {
                throw new IllegalStateException("Already Started!");
            }
            @Override
            void stop(MyFSM fsm) {
                fsm.doStop();
            }
        };

        abstract void start(MyFSM fsm);
        abstract void stop(MyFSM fsm);       
    }

    private volatile State state = State.FIRST_STATE;

    public synchronized void start() {
        state.start(this);
    }

    private void doStart() {
        state = SECOND_STATE;
    }

    public synchronized void stop() {
        state.stop(this);
    }

    private void doStop() {
        state = FIRST_STATE;
    }
}
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Brian Roach
  • 76,169
  • 12
  • 136
  • 161
1

The first pattern is slightly better for "default" methods that don't all need to be overridden.

public enum Modes {
    MODE_ONE {
        @Override public boolean canDoA() {
            return true;
        }
    },
    MODE_TWO {
        @Override public boolean canDoB() {
            return true;
        }
    },
    MODE_THREE {
        @Override public boolean canDoC() {
            return true;
        }
    };

    public boolean canDoA() {
        return false;
    }

    public boolean canDoB() {
        return false;
    }

    public boolean canDoC() {
        return false;
    }

}
Wasmoo
  • 1,130
  • 9
  • 14