8

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?

Community
  • 1
  • 1
Darkfish
  • 397
  • 1
  • 9
  • 17
  • 2
    Do you have an example of the most clearly written code and a spec and test results showing how it doesn't meat the spec? If not, you shouldn't be thinking along these lines yet. If so, post the clearly written code and I bet we could find some much more significant optimizations. – Bill K Jan 29 '10 at 18:27
  • The linked SO question tells how Enums can be used with Visitor pattern and not "visitor pattern implementation of Enums'. I think it would better if you tell what is the problem you are trying to solve. Once if you see the enums can be used as a solution to your problem then you can see if it needs to be optimized. – sateesh Jan 29 '10 at 18:28
  • 2
    This sounds like the type of micro-micro-micro-optimization which has no discernible effect in 99.99% of cases – matt b Jan 29 '10 at 18:38
  • 1
    I apologise if I was not able put forth my understanding properly in formal terms, to be honest I never got hang of such terms, although I have been using such methodologies. And I believe, yes I did use the wrong term here, like mentioned in the post by Dieter, it's called constant-specific method implementation. And I will post a sample code of what I meant by today. It was 5 in the morning here when I posted. Thanks everyone for the pointers. I agree with Matt, yet my question remains, which is more efficient even if it brings just a micro-minimal boost? – Darkfish Jan 30 '10 at 03:51
  • The second is more of a Strategy than a Visitor pattern. – helpermethod Jun 01 '10 at 07:24
  • 1
    In Effective Jave, 2nd Ed., J. Bloch makes a compelling argument that switch-case blocks should not routinely be used to iterate over enum constants. He goes on to develop the idea that using constant-specific methods in place of switch-case can often lead to less fragile, more easily maintainable code. Applying this reasoning to your question, I would say that the performance issues are not likely to be important (you'd have to profile to see), but the software engineering benefits of the constant-specific methods pattern favor their use over switch-case. – scottb Sep 09 '13 at 18:21

1 Answers1

6

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.

Dieter
  • 1,154
  • 8
  • 7
  • Thanks for the suggestion, nevertheless that was exactly what I did the second time. I'll have a look at the book as well. – Darkfish Jan 30 '10 at 07:12