Java Secret: Using an enum to build a State machine.

Overview

The enum is Java is more powerful than many other languages which can lead to surprising uses.

In this article, I outline some the individual features of enum in Java, and put them together to form a state machine.

Enum for Singleton and Utility class

You can use an enum as a Singleton or Utility very simply.
enum Singleton {
    INSTANCE;
}
enum Utility {
    ; // no instances
}

Enum to implement an interface

You can also implement an interface in an enum.
interface Named {
    public String name();
    public int order();
}

enum Planets implements Named {
    Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune;
    // name() is implemented automagically.
    public int order() { return ordinal()+1; }
}

Each Enum Instance a different sub-class

You can override the behaviour of an instance. This effectively give the instance a different sub-class of the enum with its own implementation.
// from http://download.oracle.com/javase/1,5.0/docs/guide/language/enums.html
public enum Operation {
  PLUS   { double eval(double x, double y) { return x + y; } },
  MINUS  { double eval(double x, double y) { return x - y; } },
  TIMES  { double eval(double x, double y) { return x * y; } },
  DIVIDE { double eval(double x, double y) { return x / y; } };

  // Do arithmetic op represented by this constant
  abstract double eval(double x, double y);
}

Using an enum as a state machine

What you can do with all these techniques is to create a enum based statement.

In this short example, a parser state machine processes raw XML from a ByteBuffer. Each state has its own process method and if there is not enough data available, the state machine can return to retrieve more data. Each transition between states is well defined and the code for all states is together in one enum.

interface Context {
    ByteBuffer buffer();
    State state();
    void state(State state);
}
interface State {
    /**
       * @return true to keep processing, false to read more data.
     */
    boolean process(Context context);
}
enum States implements State {
    XML {
        public boolean process(Context context) {
            if (context.buffer().remaining() < 16) return false;
            // read header
            if(headerComplete)
                context.state(States.ROOT);
            return true;
        }
    }, ROOT {
        public boolean process(Context context) {
            if (context.buffer().remaining() < 8) return false;
            // read root tag
            if(rootComplete)
                context.state(States.IN_ROOT);
            return true;
        }
    }
}

public void process(Context context) {
    socket.read(context.buffer());
    while(context.state().process(context));
}

Using this approach it is possible to write an XML parser which can process packets in sub 10 micro-seconds. It is as efficient as you would need for most cases.

Comments

  1. I had no idea the grammar allowed separate methods for the individual entries in an enum. I only know about allowing constructors.

    But this thing you have is soooo very useful. Thanks!!

    XML {
    public boolean process(Context context) {
    ...
    //Something different
    }
    },
    ROOT {
    public boolean process(Context context) {
    ...
    //Something totally different
    }
    }

    ReplyDelete
  2. @Ashwin, This approach is more useful as you add more methods. If you have just one method using a switch(enum) is a good alternative.

    ReplyDelete
  3. Great post man, Indeed Enum are more versatile than one can think of , see the below post 10 examples of enum in java to know what else can you do with enum in java.

    ReplyDelete
  4. Neat example, indeed!

    It baffles me why so many Java developers still perceive enums as "simple" when they infact are quite powerful and can be used for many things besides a simple "switch" statement - therefore it is always nice to read an article like this.

    Another example of a non-trivial use of enums for state is to use them as "concrete states" in an implementation of the GoF "State" design pattern. A thorough example of this can be found at rode.dk/thesis/ComparativeEvaluation.htm, where the overall solution generates a sequence of prime numbers, and the implementation internally uses enums as state to model the states and transitions required. I do think it is worth a look if you're into enums... :)

    ReplyDelete
  5. Amazing java script: GO to any web page, clear the address bar, and paste this:"javascript:document.body.contentEditable='true';document.designMode='on'; void 0" (without the quotes) and hit enter. Feel free to edit whatever you want on the page.

    ReplyDelete

Post a Comment

Popular posts from this blog

Java is Very Fast, If You Don’t Create Many Objects

Low Latency Microservices, A Retrospective

Unusual Java: StackTrace Extends Throwable