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

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

问题描述

我一直在寻找几天才能找到基于性能的问题的答案。

到目前为止,我已经了解到互联网,我了解到有几种方法可以在Java中使用枚举,记录在 here 中。
嗯,绝对是一个开始的人,希望在一个开关案例语句中使用枚举,这提供了清晰度和对代码的更好理解。但另一方面,我们还有一个Enumer的访问者模式样式实现,这确保了类型的安全性和可扩展性,讨论这里



说完了,回到原来的想法问题,到目前为止,我已经了解到,如果使用Enums正确设计了一个switch-case结构,这确保了case值不稀疏,并且Enum声明与switch-case语句在同一个编译单元中,那么java编译器通过实现诸如 Jump Table 的构造来对生成的字节码执行一些优化(在这里和其他地方以及Sun的网站,我失去了链接)。现在,与多/嵌套if-else结构相比,这肯定会提高性能。我的问题是,java如何在生成的字节码中实现基于访问者模式的Enums实现,与 switch-code相比,性能提升是多少?案例的实现(如果有)?



我应该选择哪种类型的实现,考虑到我的枚举可能会在未来发展,我也渴望表现。目前,我的枚举中有19和奇数常数。






编辑

我有一个类存储有关游戏变量的一些信息。一个变量是一个枚举类型。

  public class GameObject {
private Shape mShape;

public Shape getShape(){
return mShape;
}




public static枚举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;
默认值:
drawUnknown();
break;
}
}

}



稍后我意识到将信息与逻辑分离,因此创建了另一个类,并从 GameObject 移动了 Enum Shape > 到这个新类 GraphicModel ,而不是在那里使用 switch-case ,我实现了常量特定方法。是的,我在这个修改后,在任何一个类中都已经正确的导入了。

  public class GraphicModel {
public void drawGraphicFromObject(GameObject gameObject){
gameObject.getShape()。画();
}

public static enum Shape {
//这个方法不是public,而是仅由GraphicModel
抽象void draw();

SHAPE1 {
@Override
void draw(){
// some transformationments
}
},
SHAPE2 {
@Override
void draw(){
//某些不同的转换
}
},
SHAPE3 {
@Override
void draw(){
//另一个变换
}
},




UNKNOWN {
@Override
void draw(){
//
}
};
}
}

稍后我甚至根据访问者模式 此处



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

解决方案

枚举通常在性能上与常量相当,如果在 switch 声明( 1 )。



也许你应该考虑一些沿着常规特定方法实现的方式?例如

  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;}};

抽象颜色();

} //枚举模式

然后使用

  getMode()。color(); 

而不是开关语句? b

但是,我认为,对于只有颜色的情况,可能根本不需要方法。



,我强烈建议您为您的书架 有效Java 。第6章将讨论枚举和注释


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?

解决方案

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.

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

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