为什么 Java 7 中的 switch 语句比 String 的 if else 更快?
在 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
eachcase
. See thelookupswitch
. If any of these values is repeated just happens to run the code for thecase
. Otherwise, call theequals
method of the cases tied. This is much faster than ever call theequals
method only.
相关文章