在java1.7之前大家都清楚switch的比較范圍只能局限於(int 、short 、byte 、char)之間,Java 虛擬機和字節代碼這個層次上,只支持在 switch 語句中使用與整數類型兼容的類型。在1.7后switch實現字符串比較的功能。具體是如何做到的?實際上,Java虛擬機和字節碼層次上只支持switch語句中使用與整數類型兼容的類型沒有變,只是這個實現字符串比較的新特性是在編譯器這個層次上實現的。實現的機制是:將字符串之間的比較轉換為其哈希值的比較。
空口無憑,代碼為證。
源代碼:
package com.shc.test;
public class TestSwitch {
public void test(String status) {
switch (status) {
case "killed":
break;
case "alive":
break;
case "sacrificed":
break;
case "die":
break;
default:
break;
}
}
}
編譯后的class字節碼反編譯后如下:
package com.shc.test;
public class TestSwitch
{
public void test(String status)
{
String str;
switch ((str = status).hashCode()) { case -1131353987:
case 99456:
if ((str.equals("killed")) || (goto 93) || (str.equals("die"))) break; break;
case 92903629:
case 1585581907:
if ((str.equals("alive")) || (goto 93) || (str.equals("sacrificed")))
break;
}
}
}
從反編譯后的字節碼文件中可以看出, 原來用在 switch 語句中的字符串被替換成了對應的哈希值,而 case 子句的值也被換成了原來字符串常量的哈希值。經過這樣的轉換,Java 虛擬機所看到的仍然是與整數類型兼容的類型。
細心地程序猿可能發現,既然是哈希值得比較了,為什么在 case 子句對應的語句塊中仍然保留 String 的 equals 方法來進行字符串比較?這是因為哈希函數在映射的時候可能存在沖突,多個字符串的哈希值可能是一樣的。進行字符串比較是為了保證轉換之后的代碼邏輯與之前完全一樣。
