Java Enums - Switch 语句与 Enums 上的访问者模式 - 性能优势? [英] Java Enums - Switch statements vs Visitor Pattern on Enums - Performance benefits?

查看:22
本文介绍了Java Enums - Switch 语句与 Enums 上的访问者模式 - 性能优势?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

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

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.

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

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?

考虑到我的枚举未来可能会增长,而且我也热衷于性能,我应该更喜欢哪种类型的实现.目前,我的枚举中有一些 19 和奇数的常量.

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.

编辑
我有一个类存储有关游戏变量的一些信息.其中一个变量是 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,而是实现了 特定于常量的方法.是的,在此修改之后,我确实在任一类中放置了正确的导入语句.

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

后来我什至按照建议这里

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

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?

推荐答案

一般来说,如果在 switch 语句中使用枚举,其性能与 int 常量相当(1).

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

然后使用

getMode().color();

而不是 switch 语句?!

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

However, I think that for a "get a color only case", there is maybe no need for methods at all.

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

In general, I highly recommend you Effective Java for your bookshelf. Chapter 6 would be the one that discusses Enums and Annotations.

这篇关于Java Enums - Switch 语句与 Enums 上的访问者模式 - 性能优势?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆