Java 枚举 - 枚举上的 Switch 语句与访问者模式 - 性能优势?

标签 java enums performance switch-statement visitor-pattern

我已经搜索了好几天来找到这个基于性能的问题的答案。
到目前为止,在浏览 Internet 之后,我了解到有几种方法可以在 Java 中使用枚举,详细记录在 here 中。 . 好吧,作为初学者肯定会喜欢在 switch-case 语句中使用枚举,这样可以使代码更加清晰和更好地理解。但另一方面,我们也有一个 Visitor 模式 风格的枚举实现,这确保了类型安全和可扩展性,已讨论 here .

话虽如此,回到这个问题背后的最初想法,到目前为止,我了解到如果使用枚举正确设计了一个 switch-case 结构,这确保了 case 值不稀疏,并且 Enum 声明是在与 switch-case 语句相同的编译单元中,java 编译器通过实现诸如 Jump Table(在 here 和其他地方以及Sun 的网站,我失去了链接)。现在,与多重/嵌套 if-else 结构相比,这无疑提高了性能。

我的问题是,java 如何在生成的字节码中实现基于访问者模式的枚举实现?与基于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/strong> 到这个新类 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() {
                // 
            }
        };
    }
}

后来我什至按照建议基于访问者模式实现了这个here

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

最佳答案

一般来说,如果在 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 章将讨论枚举和注释

关于Java 枚举 - 枚举上的 Switch 语句与访问者模式 - 性能优势?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2164124/

相关文章:

c# - 使用枚举(构建列表)

c++ - 为什么我不能为 C++ 枚举类型变量分配正确的值?

java - 关于文件标记化、对象值设置和标记位置枚举的 API 设计

android - 如何使用应用内更新库防止内存泄漏

c# - 什么是 "Sync Block"以及减少计数的技巧

oracle - Oracle 11gR2 中使用条件的多次更新

java - 如何在 Java 中交换所有其他字母/字符?

java - java 的 Finished 部分握手失败,但curl 则不然

使用 "..."选择枚举元素

java - JPA 和新手的关系映射问题