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

11,067

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.

Share:
11,067

Related videos on Youtube

Darkfish
Author by

Darkfish

Software Developer in Python, Ruby, Java and related frameworks such as, Ruby on Rails, Django, Spring, etc. Love coding in C and Ruby. Mostly do freelance work for Universities that have specific requirements for their experiments and are unable to use any off-the-shelf product.

Updated on April 15, 2022

Comments

  • Darkfish
    Darkfish about 2 years

    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?

    • Bill K
      Bill K over 14 years
      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.
    • matt b
      matt b over 14 years
      This sounds like the type of micro-micro-micro-optimization which has no discernible effect in 99.99% of cases
    • Darkfish
      Darkfish over 14 years
      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?
    • scottb
      scottb over 10 years
      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.
  • Darkfish
    Darkfish over 14 years
    Thanks for the suggestion, nevertheless that was exactly what I did the second time. I'll have a look at the book as well.