目前Java中switch語(yǔ)句支持的數(shù)據(jù)類(lèi)型包括:byte、short、int、char、String以及Enum,那么switch語(yǔ)句是如何實(shí)現(xiàn)的呢?
一、switch對(duì)整型的支持
public void switchInt(int value) {
switch (value) {
case 1:
System.out.println("1");
break;
case 2:
System.out.println("2");
break;
default:
System.out.println("Error value");
break;
}
}
使用javap -c進(jìn)行反編譯可以看到:
public void switchInt(int);
Code:
0: iload_1
1: lookupswitch { // 2
1: 28
2: 39
default: 50
}
28: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
31: ldc #14 // String 1
33: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
36: goto 58
39: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
42: ldc #15 // String 2
44: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
47: goto 58
50: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
53: ldc #16 // String Error value
55: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
58: return
可以看到,switch對(duì)整型的支持是直接比較int的值(如果換做byte和short,反編譯后是一樣的)。
二、switch對(duì)char的支持
public void switchChar(char value) {
switch (value) {
case 'a':
System.out.println("a");
break;
case 'b':
System.out.println("b");
break;
default:
System.out.println("Error value");
break;
}
}
使用javap -c進(jìn)行反編譯可以看到:
public void switchChar(char);
Code:
0: iload_1
1: lookupswitch { // 2
97: 28
98: 39
default: 50
}
28: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
31: ldc #17 // String a
33: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
36: goto 58
39: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
42: ldc #18 // String b
44: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
47: goto 58
50: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
53: ldc #16 // String Error value
55: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
58: return
可以看到,switch對(duì)char的支持是將char轉(zhuǎn)換成int值,再做比較的。
三、switch對(duì)字符串的支持
public void switchString(String str) {
switch (str) {
case "hello":
System.out.println("hello");
break;
case "welcome":
System.out.println("welcome");
break;
default:
System.out.println("Error value");
break;
}
}
使用javap -c進(jìn)行反編譯可以看到:
public void switchString(java.lang.String);
Code:
0: aload_1
1: astore_2
2: iconst_m1
3: istore_3
4: aload_2
5: invokevirtual #19 // Method java/lang/String.hashCode:()I
8: lookupswitch { // 2
99162322: 36
1233099618: 50
default: 61
}
36: aload_2
37: ldc #20 // String hello
39: invokevirtual #21 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
42: ifeq 61
45: iconst_0
46: istore_3
47: goto 61
50: aload_2
51: ldc #22 // String welcome
53: invokevirtual #21 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
56: ifeq 61
59: iconst_1
60: istore_3
61: iload_3
62: lookupswitch { // 2
0: 88
1: 99
default: 110
}
88: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
91: ldc #20 // String hello
93: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
96: goto 118
99: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
102: ldc #22 // String welcome
104: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
107: goto 118
110: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
113: ldc #16 // String Error value
115: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
118: return
可以看到,switch對(duì)字符串的支持是先比較hashCode,再用equals做校驗(yàn),最后用得到的值再switch一次。
四、switch對(duì)枚舉類(lèi)型的支持
public void switchEnum(State state) {
switch (state) {
case Start:
System.out.println("Start");
break;
case InProcessing:
System.out.println("InProcessing");
break;
case Finished:
System.out.println("Finished");
break;
default:
System.out.println("Error state");
break;
}
}
使用javap -c進(jìn)行反編譯可以看到:
public void switchEnum(pers.wukong.onestep.State);
Code:
0: getstatic #6 // Field pers/wukong/onestep/Test$1.$SwitchMap$pers$wukong$onestep$State:[I
3: aload_1
4: invokevirtual #7 // Method pers/wukong/onestep/State.ordinal:()I
7: iaload
8: tableswitch { // 1 to 3
1: 36
2: 47
3: 58
default: 69
}
36: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
39: ldc #9 // String Start
41: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
44: goto 77
47: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
50: ldc #11 // String InProcessing
52: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
55: goto 77
58: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
61: ldc #12 // String Finished
63: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
66: goto 77
69: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
72: ldc #13 // String Error state
74: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
77: return
switch對(duì)枚舉類(lèi)型的支持和我預(yù)想的不一樣,它是維護(hù)了一個(gè)SwitchMap,枚舉的ordinal()方法的返回值作為Key,value是從1開(kāi)始遞增的。switch比較的就是這個(gè)value值。
總結(jié)
switch其實(shí)都是通過(guò)int來(lái)實(shí)現(xiàn)的,不同的是,各種數(shù)據(jù)類(lèi)型轉(zhuǎn)換int的方式是不一樣的。