8

我一直在寻找几天来找到这个基于性能的问题的答案。
到目前为止,在挖掘 Internet 之后,我了解到有几种方法可以在 java 中使用枚举,这里有很好的记录。好吧,作为初学者,肯定会喜欢在switch-case语句中使用 Enums,它可以提供清晰的代码并更好地理解代码。但另一方面,我们也有 Enums 的访问者模式样式实现,它确保了类型安全性和可扩展性,在此处讨论。

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

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

考虑到我的枚举将来可能会增长,而且我也热衷于性能,我应该更喜欢哪种类型的实现。目前,我的枚举中有一些 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;
        }
    }

}

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

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() {
                // 
            }
        };
    }
}

后来我什至根据这里建议的访问者模式实现了这个

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

4

1 回答 1

6

一般来说,如果在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

然后使用

getMode().color();

而不是switch语句?!

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

一般来说,我强烈推荐你的书架使用Effective Java。第 6 章将讨论Enums 和 Annotations

于 2010-01-29T19:03:58.010 回答