在Java7以前,switch只能支持 byte、short、char、int或者其對應的封裝類以及Enum類型。在Java7中,呼籲好久的String支持也終於被加上了。
例如,下面是一段switch中使用String的示例代碼。
1 public class Test { 2 3 public void test(String str) { 4 switch(str) { 5 case "abc": 6 System.out.println("abc"); 7 break; 8 case "def": 9 System.out.println("def"); 10 break; 11 default: 12 System.out.println("default"); 13 } 14 } 15 16 }
在switch語句中,String的比較用的是String.equals,所以你們能夠放心的使用。
須要注意的是,傳給switch的String變量不能爲null,同時switch的case子句中使用的字符串也不能爲null。
爲何要有這些非null的限制呢?其實,咱們只要將這段代碼反彙編出來,看一下底層究竟是如何實現的,就能夠明白了。下面是彙編出來的代碼。
Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return
public void test(java.lang.String);
Code:
0: aload_1
1: astore_2
2: iconst_m1
3: istore_3
4: aload_2
5: invokevirtual #2; //Method java/lang/String.hashCode:()I
8: lookupswitch{ //2
96354: 36;
99333: 50;
default: 61 }
36: aload_2
37: ldc #3; //String abc
39: invokevirtual #4; //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 #5; //String def
53: invokevirtual #4; //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 #6; //Field java/lang/System.out:Ljava/io/PrintStream;
91: ldc #3; //String abc
93: invokevirtual #7; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
96: goto 118
99: getstatic #6; //Field java/lang/System.out:Ljava/io/PrintStream;
102: ldc #5; //String def
104: invokevirtual #7; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
107: goto 118
110: getstatic #6; //Field java/lang/System.out:Ljava/io/PrintStream;
113: ldc #8; //String default
115: invokevirtual #7; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
118: return
}
估計有些同窗懶得看這些彙編,其實把上面的彙編代碼用Java寫出來就是下面的樣子了。
寫到這裏,你們應該能明白爲何不能用null了吧。
1 public class Test { 2 public void test(String str) { 3 int i = -1; 4 switch(str.hashCode()) { 5 case 96354: // "abc".hashCode() 6 if (str.equals("abc")) { 7 i = 0; 8 } 9 break; 10 case 99333: // "def".hashCode() 11 if (str.equals("def")) { 12 i = 1; 13 } 14 break; 15 default: 16 break; 17 } 18 19 switch(i) { 20 case 0: 21 System.out.println("abc"); 22 break; 23 case 1: 24 System.out.println("def"); 25 break; 26 default: 27 System.out.println("default"); 28 } 29 } 30 }
若是switch傳入的null,那麼在運行時對一個null對象調用hashCode方法會出現NullPointerException。
若是switch的case寫的是null,那麼在編譯時沒法求出hashCode,所以在編譯時就會報錯了。
switch支持String只是一個語法糖,由javac來負責生成相應的代碼。底層的JVM在switch上並無進行修改。
參考
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
若是switch傳入的null,那麼在運行時對一個null對象調用hashCode方法會出現NullPointerException。
若是switch的case寫的是null,那麼在編譯時沒法求出hashCode,所以在編譯時就會報錯了。
switch支持String只是一個語法糖,由javac來負責生成相應的代碼。底層的JVM在switch上並無進行修改。