问题描述
在 Java 7 中,string 对象可以在 switch 语句的表达式中.有人可以从 官方文档一个>?
In Java 7 a string object can be in the expression of a switch statement. Can someone explain the below statement from official documentation?
Java 编译器从使用 String 对象的 switch 语句生成的字节码通常比从链式 if-then-else 语句生成的字节码效率更高.
The Java compiler generates generally more efficient bytecode from switch statements that use String objects than from chained if-then-else statements.
推荐答案
Java代码
有两个版本的类,例如
Java Code
Having two versions of a class, e.g.
使用 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 方法来比较字符串,直到找到为止.
Conclusion
In the first version compares the string by calling the equals method for each condition, until it is found.
在第二个版本中是获取第一个hashCode的字符串.然后将其与每个case的值hashCode进行比较.请参阅 lookupswitch.如果这些值中的任何一个重复,则恰好运行 case 的代码.否则,调用绑定案例的 equals 方法.这比仅调用 equals 方法要快得多.
In the second version is obtained first hashCode of the string. Then this is compared with the values ??hashCode each case. See the lookupswitch. If any of these values ??is repeated just happens to run the code for the case. Otherwise, call the equals method of the cases tied. This is much faster than ever call the equals method only.