当前位置: 首页 > 面试题库 >

Java枚举-在枚举上转换语句与访客模式-性能优势?

长孙正卿
2023-03-14
问题内容

我已经搜寻了几天,以找到针对此性能问题的答案。
到目前为止,在深入研究Internet之后,我了解到有几种使用Java中的Enums的方法,在这里有充分的记录。好吧,毫无疑问,作为一个入门者,我们希望在
switch-case 语句中使用Enums ,它可以使代码更清晰并更好地理解代码。但是另一方面,我们也有Enums 的 Visitor模式
样式实现,该实现可确保类型安全和可扩展性

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

我的问题是,java如何在生成的字节码中实现基于访客模式的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;
        }
    }

}

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

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需要在同一 编译单元中
同时包含 enum 声明和 switch 语句。我应该在我的 GraphicModel 类中使用基于 开关 的实现还是 特定
常量的方法 实现?更确切地说,性能有何区别? ______
*


问题答案:

也许您应该宁愿考虑一些 特定常量的方法实现 ?例如

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 语句?!

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



 类似资料:
  • 让我们看看一个需要诉诸于代码的场景,来考虑为何此时使用枚举更为合适且实用。假设我们要处理 IP 地址。目前被广泛使用的两个主要 IP 标准:IPv4(version four)和 IPv6(version six)。这是我们的程序可能会遇到的所有可能的 IP 地址类型:所以可以 枚举 出所有可能的值,这也正是此枚举名字的由来。 任何一个 IP 地址要么是 IPv4 的要么是 IPv6 的,而且不能

  • 问题内容: 在JDK1.5之前的Java中,“ Typesafe Enum”模式是实现只能接受有限数量的值的类型的常用方法: (例如,参见Bloch的Effective Java中的第21项)。 现在在JDK1.5 +中,显然可以使用“官方”方式enum: 显然,该语法更好,更简洁(不需要为值明确定义字段,适当toString()提供),但是到目前为止enum看起来非常类似于模式。 我知道的其他差

  • 问题内容: 通过阅读SCJP书籍,我在第1章“自测”中发现了类似的内容: 注意:代码编译正常。我不明白的是为什么我们可以从变量访问DOG,CAT或FISH常量。我认为(并且也写在书中)DOG,FISH,CAT是常量,其实现方式类似于。 所以,如果它们确实是静态的,为什么我们可以从中访问它们呢?最后一行是我熟悉的方式。 问题答案: 写作 和写作一样。也就是说,编译器将用其编译时类型Animal替换变

  • 本文向大家介绍Java枚举与.net枚举区别详解,包括了Java枚举与.net枚举区别详解的使用技巧和注意事项,需要的朋友参考一下 通过一段时间的项目实践,发现java中的枚举与.net中的枚举有很大的差别,初期造成了我对java中的枚举一些错误理解及部分有缺陷的应用,其实追其原因还是因为我会习惯性的认为java的枚举在作用以及定义上与.net应该是差不多的,毕竟两者都是高级语言,语言上也有很多相

  • 问题内容: 我没有真正的运气可以通过使用Google来获得这种比较的简洁答案,我想先问一下,而不是自己进行耗时的评估。 我相当确定使用Enums的switch语句将比if-then-else语句执行得更快,尽管是否存在显着差异是另一个问题。 有人可以帮我一下吗? 感谢大家的快速反应,我会在以后的项目中牢记这一点。 问题答案: 是的,是的,因为一般而言,switch语句的运行速度比if / else

  • 枚举具有名为'hash value'的属性,该属性是枚举内的索引。