You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
这个特性现在已经被实现,`javac`with a ["de-sugaring peocess"](http://blogs.oracle.com/darcy/entry/project_coin_string_switch_anatomy)。一个高级的,清楚的使用String常量的语法能在case声明中被使用,会在编译时扩展成为更复杂的代码模式,生成的代码使用jvm指令也一直存在。
System.out.println("Application is running on Active mode");
23
+
break;
24
+
case "PASSIVE":
25
+
System.out.println("Application is running on Passive mode");
26
+
break;
27
+
case "SAFE":
28
+
System.out.println("Application is running on Safe mode");
29
+
}
30
+
}
31
+
}
32
+
```
33
+
编译后再反编译的代码:
34
+
```
35
+
import java.io.PrintStream;
36
+
37
+
public class StringInSwitchCase{
38
+
public StringInSwitchCase() { }
39
+
40
+
public static void main(string args[]) {
41
+
String mode = args[0];
42
+
String s; switch ((s = mode).hashCode()) {
43
+
default: break;
44
+
case -74056953:
45
+
if (s.equals("PASSIVE")) {
46
+
System.out.println("Application is running on Passive mode");
47
+
}
48
+
break;
49
+
case 2537357:
50
+
if (s.equals("SAFE")) {
51
+
System.out.println("Application is running on Safe mode");
52
+
}
53
+
break;
54
+
case 1925346054:
55
+
if (s.equals("ACTIVE")) {
56
+
System.out.println("Application is running on Active mode");
57
+
}
58
+
break;
59
+
}
60
+
}
61
+
}
62
+
```
63
+
64
+
包含case string的 switch 语句,在编译时会转为为嵌套代码(switch+if)。第一个switch将 case 中的string转为唯一的integer值。这个integer值就是原先string的hashcode值。在case的逻辑中,会加入if语句,这个if语句用于进一步检查string值是否跟原先的case string匹配。这样可以防止hash碰撞,确保代码的健壮。这本质上是一种语法糖,既支持了string作为case值这一特性,又能确保逻辑正确性。
15
65
16
66
**Switchs in the JVM**
17
-
在switch的更多深层技术上,可以参考JVM规范,[compliation of switch statements](http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html#jvms-3.10)有响应的描述。简单概括说,根据使用的常量的多少,switch有两种不同的JVM指令来执行,每种情况下都取决于使用整数常量来有效的执行。
18
67
19
-
如果常量很多,case会在一个指令表被用作索引(减去最小值后)——`tablewitch`指令
20
-
如果常量相对较少,那么可用二分查找来找到正确的case--`lookupswitch`指令
68
+
switch的更多深层技术实现,可以参考JVM规范,[compliation of switch statements](http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html#jvms-3.10)。简单概括说,根据使用的常量的多寡,switch会对应到两种不同的JVM指令。JVM指令有所不同,归根结底都是为了代码的效率。
两种指令在编译时都需要将整数常量赋值给每个case。在运行时,虽然`tableswitch`O(1)的性能通常要好于`lookupswitch`O(log(n))的性能,但是前者需要一定的分析来决定是否有足够的case来满足时间空间的平衡。Bill Venners的文章[a great article](http://www.artima.com/underthehood/flowP.html)在细节上讲述的更多,以及涉及到从底层的出发,来看其他java流程控制指令。
这两种指令,都要求在编译时确保case的对应值是integer常量。在运行时,虽然`tableswitch`O(1)的性能通常要好于`lookupswitch`O(log(n))的性能。但是前者需要更多的空间开销,因此需要兼顾空间及时间综合考虑性价比。Bill Venners的文章[a great article](http://www.artima.com/underthehood/flowP.html)有更多深入的分析。
0 commit comments