Java Enums - 在枚举上切换语句与访问者模式 - 性能优势?

Dar*_*ish 7 java performance enums visitor-pattern switch-statement

我一直在寻找这个基于性能的问题的答案.
到目前为止,在挖掘了互联网之后,我了解到有几种方法可以在java中使用Enums,这里有详细记载.好吧,作为一个初学者,我希望在switch-case语句中使用Enums ,这样可以提供清晰度并更好地理解代码.但另一方面,我们还有一个访问者模式样式的Enums实现,它确保了类型的安全性和可扩展性,这里讨论.

话虽如此,并回到这个问题背后的原始想法,到目前为止我已经了解到如果使用Enums正确设计switch-case结构,这确保了case值不稀疏,并且Enum声明是相同的编译单元作为switch-case语句,java编译器通过实现跳转表这样的构造对生成的字节码执行一些优化(在这里和其他地方讨论过,在Sun的网站上,我丢失了链接).现在,与多个/嵌套的if-else构造相比,这肯定会提升性能.

我的问题是,java如何在生成的字节码中实现基于访问者模式的Enums实现,与基于switch-case的实现(如果有的话)相比,性能提升了多少?

我应该选择哪种类型的实现,考虑到我的Enums可能在未来增长,我也热衷于性能.目前,我的Enum中有一些19和奇数常量.


编辑
我有一个类存储有关游戏变量的一些信息.其中一个变量是Enum类型.

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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

}

后来我意识到将信息与逻辑分离,因此创建了另一个类并将Enum ShapeGameObject移动到这个新类GraphicModel,而不是在那里使用switch-case,我实现了特定于常量的方法.是的,我在这个修改后确实在任一类中都放了适当的import语句.

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() {
                // 
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

后来我甚至根据这里建议的访客模式实现了这个

那么,我需要知道的是哪种实施方式更有效?当然,要在编译时将switch-case转换为跳转表,java需要在同一编译单元中使用枚举声明和switch语句.我应该在我的GraphicModel类中使用基于开关的实现还是常量特定的方法实现?相反,要明确,性能有何不同?

Die*_*ter 5

一般而言,如果在switch语句 ( 1 ) 中使用枚举,则其性能可与int常量相媲美。

也许你应该考虑一些与常量特定方法实现相关的东西?例如

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
Run Code Online (Sandbox Code Playgroud)

然后使用

getMode().color();
Run Code Online (Sandbox Code Playgroud)

而不是switch语句?!

但是,我认为对于“仅获取颜色的情况”,可能根本不需要方法。

总的来说,我强烈推荐你的书架上使用Effective Java。第 6 章将讨论枚举和注释