java - 为什么 Java 7 中 String 的 switch 语句比 if else 快?

标签 java if-statement switch-statement java-7

Java 7 中,string 对象可以在 switch 语句的表达式中。有人可以从 official documentation 解释以下声明吗? ?

The Java compiler generates generally more efficient bytecode from switch statements that use String objects than from chained if-then-else statements.

最佳答案

Java代码

有一个类的两个版本,例如

使用if-then-else:

public class IfThenElseClass {
    public static void main(String[] args) {
        String str = "C";
        if ("A".equals(str)) {

        } else if ("B".equals(str)) {

        } else if ("C".equals(str)) {

        }
    }
}

使用开关:

public class SwitchClass {
    public static void main(String[] args) {
        String str = "C";
        switch (str) {
            case "A":
                break;
            case "B":
                break;
            case "C":
                break;
        }
    }
}

字节码

让我们看一下字节码。获取 if-then-else 版本的字节码:

Compiled from "CompileSwitch.java"
public class CompileSwitch {
  public CompileSwitch();
    Code:
       0: aload_0
       1: invokespecial #8  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #16 // String C
       2: astore_1
       3: ldc           #18 // String A
       5: aload_1
       6: invokevirtual #20 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
       9: ifne          28
      12: ldc           #26 // String B
      14: aload_1
      15: invokevirtual #20 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      18: ifne          28
      21: ldc           #16 // String C
      23: aload_1
      24: invokevirtual #20 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      27: pop
      28: return
}

获取switch版本的字节码:

Compiled from "CompileSwitch.java"
public class CompileSwitch {
  public CompileSwitch();
    Code:
       0: aload_0
       1: invokespecial #8 // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #16 // String C
       2: astore_1
       3: aload_1
       4: dup
       5: astore_2
       6: invokevirtual #18 // Method java/lang/String.hashCode:()I
       9: lookupswitch  { // 3
                    65: 44
                    66: 56
                    67: 68
               default: 77
          }
      44: aload_2
      45: ldc           #24 // String A
      47: invokevirtual #26 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      50: ifne          77
      53: goto          77
      56: aload_2
      57: ldc           #30 // String B
      59: invokevirtual #26 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      62: ifne          77
      65: goto          77
      68: aload_2
      69: ldc           #16 // String C
      71: invokevirtual #26 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
      74: ifne          77
      77: return
}

结论

  • 在第一个版本中,通过为每个条件调用 equals 方法来比较字符串,直到找到为止。

  • 在第二个版本中获取第一个hashCode的字符串。然后将其与每个 case 的值 hashCode 进行比较。请参阅 lookupswitch。如果重复这些值中的任何一个,恰好会运行 case 的代码。否则,调用并列案例的 equals 方法。这比仅调用 equals 方法要快得多。

关于java - 为什么 Java 7 中 String 的 switch 语句比 if else 快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10836055/

相关文章:

java - 当字符串包含破折号时打开枚举

c - 有什么办法可以限制在 switch 语句中可以作为 case 的值吗?

java - 如何访问java中对象的通用数组列表中的项目字段?

java - 如何解决? java控制台应用程序:System. in.readLine问题:用户看不到他正在输入的内容

java - 为了交换该数组中的数字,我缺少什么? java

R - if_else 分配 na 值

java - hibernate 插入选项

mysql:内部查询在 selectif 语句中不起作用

java - 条件运算符(!=)(If-else 语句)

java - 在十二生肖确定器中接收有效输入的无效 I/O