【问题标题】:Is there anything like branch/jump table in Java?Java中有没有类似分支/跳转表的东西?
【发布时间】:2010-10-07 13:51:18
【问题描述】:

Java 有类似分支或跳转表的东西吗?

一个分支或跳转表是according to wikipedia

一个术语,用于描述使用分支指令表将程序控制(分支)转移到程序的另一部分(或可能已动态加载的不同程序)的有效方法。

Java 有类似的东西还是我只需要使用 if/else if/else 或 case 语句?

【问题讨论】:

    标签: java branch jump-table


    【解决方案1】:

    Java 有一个switch statement,但它是否编译为字节码中的跳转表取决于实现。通常,如果编译器在您的 switch 语句中为每种情况找到合适的常量,他们会为您构建一个跳转表。不过,我不确定您是否应该真正关心它是如何实现的。如果您首先使用 Java 进行编码,那么让编译器和 JIT 为您处理这些事情可能会很好。

    请注意,switch 仅适用于整数原始类型和枚举,因此如果您使用其他对象类型,您确实需要使用 if/else 语句(并且您可能不应该比较双精度或浮动以求相等)。

    最后,即使枚举引用在技术上是“恒定的”,一些编译器只会在您打开枚举时生成跳转表如果您的 switch 语句与枚举所在的编译单元相同定义。否则,它将为您生成一个 if/else 链(就像您对常规对象所做的那样)。有关详细信息,请参阅java.net forums on extending switch usage for Objects

    【讨论】:

      【解决方案2】:

      是的,绝对的。

      如果您编写 switch 语句,则根据不同的情况,switch 将转换为字节码中的 tableswitch 指令。一般

      • 开关必须依赖于一个 int 值
      • 最高 int 值和最低 int 值不能相距太远

      实现这一点的最简单方法是使用由编译器专门处理的 java 枚举。相关文档在Java Virtual Machine Specification。当然,JIT 编译器几乎可以肯定地将这些直接转换为您运行的任何平台的机器代码中的非常快速的开关。

      话虽如此,真正对您问题的回答是“这是您在编写机器代码时担心的事情,而不是使用高级语言进行编程”。

      【讨论】:

        【解决方案3】:

        您可以使用枚举来执行此操作。

        // doesn't work in c#
        enum Switch implements Runnable {
           OPTION1() {
             public void run() {
                // do something.
             }
           },
           OPTION2() {
             public void run() {
                // do something.
             }
           },
           OPTION3() {
             public void run() {
                // do something.
             }
           }
        }
        
        Switch option = Switch.valueOf(switchOptionTest);
        option .run();
        //or
        Switch[] options = Switch.values();
        Switch option = options[nSwitchOption];
        option .run();
        

        【讨论】:

          【解决方案4】:

          我认为您不需要 Java 中的那种性能技巧。我会首先专注于编写可读代码并使用体面的算法 - 这些将提供比您所讨论的更多的性能优势。

          在大多数独立应用程序中,绝大多数时间都花在等待用户做某事上。在大多数 Web 应用程序中,在 JVM 中运行字节码的时间应该被网络时间、数据库时间或业务逻辑所淹没。

          如果您真的担心部分 Java 应用程序的性能,可以将其移至 JNI 代码中并完全绕过 Java 解释器。

          【讨论】:

            【解决方案5】:

            一个术语,用于描述使用分支指令表将程序控制(分支)转移到程序的另一部分(或可能已动态加载的不同程序)的有效方法。”

            传递程序控制的一种方法是调用函数。当您有多个可供选择时,调用正确函数的一种方法是将其与对象的类型分开。这叫做多态性。 Java 和其他面向对象的语言具有多态性,通过继承(子类化)实现。不确定它是如何在 Java 中实现的,但在 C++ 中(通常?或总是?)每个对象中都有一个指针,指向它的类的 v-table,其中包含指向虚函数的指针。

            我严重怀疑缺少用户定义的跳转表会削弱 Java 应用程序的性能。

            【讨论】:

            • 完美答案。希望我能 +3
            【解决方案6】:

            Java 有类似的东西还是我只需要使用 if/else if/else 或 case 语句?

            我认为 case 语句(在 java 中带有 switch )是等价的。

            此外,在 OOP 中,开关可以被编码一次,然后让多态性工作。

            发件人:http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html

            这取决于您的要求。

            【讨论】:

            • +1 和 keysersoze,/-1 给其他所有人,因为他们没有意识到 OOP 是调度表的实现!这就像是在问为什么 C 没有 push 命令来直接操作堆栈。
            • +1:除非有一些非常不寻常的约束,或者解决方案是一次性且非常非正式/小型的,否则虚拟调度应该是首选的调度机制。
            • 另一个很棒的 Google Techtalk 可以看到用多态性替换条件(这是 Martin Fowler 的书中的一种重构模式 - '重构:改进现有代码的设计')可以在这里找到:youtube.com/watch?v=4F72VULWFvc
            【解决方案7】:

            您所说的这种分支/跳转表不是由 Java、C 等高级语言直接提供的,而是由编译器以机器码或字节码生成的。换句话说,您的编译器可能会使用它们,但您看不到它们。

            【讨论】:

              【解决方案8】:

              您可以使用反射和存储匿名内部类的通用 HashMap 来做到这一点,但这将是一个可怕的 hack。

              由于本机匿名方法,在 C# 中执行此操作非常优雅,但在 java 中则不然。

              【讨论】:

                【解决方案9】:

                认为这就是一些 switch 语句是如何“在后台”实现的。

                除此之外,您可以使用HashMap<whatever, Method> 之类的方法执行类似的操作,其中使用map.get(something).invoke()。但这有点违背了目的,因为它不会像跳转表那样快,而且我想不出一个好的案例,OOP 编程/多态不会更好、更清洁地完成这项工作。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-01-20
                  • 1970-01-01
                  • 2011-02-26
                  • 1970-01-01
                  • 2020-03-11
                  • 2011-12-07
                  • 2020-11-10
                  相关资源
                  最近更新 更多