Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Enums - Switch statements vs Visitor Pattern on Enums - Performance benefits?

I have been searching around for days to find an answer to this performance based issue.
After digging the Internet so far I have learned that there are couple of ways to use the Enums in java, well documented in here. Well, definitely as a starter one would like use Enums in a switch-case statement, which provides clarity and better understanding of the code. But on the other hand we have a Visitor pattern style implementation of the Enums as well, which ensures type safety and extensibility, Discussed here.

Having said that, and coming back to original idea behind this question, so far I have learned that if a switch-case construct is properly designed using Enums, which ensures that case values are not sparse, and that the Enum declaration is in the same compilation unit as the switch-case statement, the java compiler performs some optimisation on the produced byte-code by implementing such construct as a Jump Table (discussed in here and elsewhere as well on Sun's website, to which I lost the link). Now, this definitely gives a boost to the performance compared to multiple/nested if-else construct.

My question is, how does java implement the visitor pattern based implementation of Enums in the resulting byte-code and what is the performance boost while compared to switch-case based implementation, if any?

And which type of implementation should I prefer, considering my Enums may grow in future and I am keen on performance as well. Currently, I have some 19 and odd constants in my Enum.


EDIT
I have a class that stores some information about variables of a game. One of the variables being an Enum type.

public class GameObject {
    private Shape mShape;

    public Shape getShape() {
        return mShape;
    }
    .
    .
    .

    public static enum Shape {
        SHAPE1, SHAPE2, SHAPE3, SHAPE4, ..., SHAPE20
    };

    public void drawShape() {
        switch (this.mShape) {
        case SHAPE1:
            drawShape1();
            break;
        case SHAPE2:
            drawShape2();
            break;
        case SHAPE3:
            drawShape3();
            break;
        case SHAPE4:
            drawShape4();
            break;
        .
        .
        .
        .
        .
        case SHAPE20:
            drawShape20();
            break;
        default:
            drawUnknown();
            break;
        }
    }

}

Later I realised of separating the information from logic, and hence created another class and moved the Enum Shape from GameObject to this new class GraphicModel, and instead of having switch-case there, I implemented constant-specific methods. And yes I did put proper import statements in either class after this modification.

public class GraphicModel {
    public void drawGraphicFromObject(GameObject gameObject) {
        gameObject.getShape().draw();
    }

    public static enum Shape {
        // This method is not public, instead is only called by GraphicModel
        abstract void draw();

        SHAPE1 {
            @Override
            void draw() {
                // some transformations
            }
        },
        SHAPE2 {
            @Override
            void draw() {
                // Some different transformation
            }
        },
        SHAPE3 {
            @Override
            void draw() {
                // Yet another transform
            }
        },
        .
        .
        .
        .
        UNKNOWN {
            @Override
            void draw() {
                // 
            }
        };
    }
}

Later on I even implemented this based on visitor pattern as suggested here

So, what I need to know is that which way of implementation is more efficient? Definitely, for switch-case to be converted to jump tables on compilation, java requires both enum declaration and switch statements in the same compilation unit. Should I use switch based implementation or constant-specific method implementation in my GraphicModel class? Rather, to be clear, what's the difference in performance?

like image 951
Darkfish Avatar asked Jan 29 '10 18:01

Darkfish


1 Answers

Enums are, generally speaking, comparable in performance to int constants, if used in a switch statement (1).

Maybe you should rather consider something along the lines of constant specific method implementations? e.g.

public enum Mode {

  ON { Color color() {return Color.GREEN;}},
  OFF { Color color() {return Color.RED;}},
  STANDBY { Color color() {return Color.YELLOW;}},
  DEFAULT { Color color() {return Color.BLACK;}};

  abstract Color color();

}//enum Mode

And then use

getMode().color();

instead of a switch statement?!

However, I think that for a "get a color only case", there is maybe no need for methods at all.

In general, I highly recommend you Effective Java for your bookshelf. Chapter 6 would be the one that discusses Enums and Annotations.

like image 165
Dieter Avatar answered Sep 23 '22 18:09

Dieter