問題:
* byte可以作為switch的表達式嗎? 可以
* long可以作為switch的表達式嗎? 不可以
* String可以作為switch的表達式嗎? 可以
在JDK1.7之前,switch(expression)中,expression只能是一個整數表達式或者枚舉常量,整數表達式可以是int類型或Integer包裝類型。
由於,byte,short,char都可以隱式轉換為int類型,所以,這些類型也可以用作表達式。
JDK1.7以后,switch表達式也可以為String類型,具體原理參考這位大神的博客。
【轉載】
在jdk1.7中switch語句可以支持String類型的參數,實際上,這個新特性是在編譯器這個層次上實現的。而在 Java 虛擬機和字節代碼這個層次上,還是只支持在 switch 語句中使用與整數類型兼容的類型。這么做的目的是為了減少這個特性所影響的范圍,以降低實現的代價。在編譯器層次實現的含義是,雖然開發人員在 Java 源代碼的 switch 語句中使用了字符串類型,但是在編譯的過程中,編譯器會根據源代碼的含義來進行轉換,將字符串類型轉換成與整數類型兼容的格式。不同的 Java 編譯器可能采用不同的方式來完成這個轉換,並采用不同的優化策略。
例如:
public class Test { public void test(String type) { switch (type) { case "情況A": break; case "情況B": break; default: break; } } }
編譯成class之后,再通過反編譯工具得到如下代碼:
public class Test { public void test(String paramString) { String str = paramString; int i = -1; switch (str.hashCode()) { case 24455345: if (!str.equals("情況A")) break; i = 0; break; case 24455346: if (!str.equals("情況B")) break; i = 1; } switch (i) { case 0: break; case 1: break; } } }
從上面的代碼中可以看出,原來用在 switch 語句中的字符串被替換成了對應的哈希值,而 case 子句的值也被換成了原來字符串常量的哈希值。經過這樣的轉換,Java 虛擬機所看到的仍然是與整數類型兼容的類型。在這里值得注意的是,在 case 子句對應的語句塊中仍然需要使用 String 的 equals 方法來進行字符串比較。這是因為哈希函數在映射的時候可能存在沖突,多個字符串的哈希值可能是一樣的。進行字符串比較是為了保證轉換之后的代碼邏輯與之前完全一樣。