為什么switch不支持long


switch 支持的類型

在 Java 語言規范里中,有說明 switch 支持的類型有:char、byte、short、int、Character、Byte、Short、Integer、String、enum。

為什么不支持 long ?

為什么只支持上面幾種?int、String 都可以,為什么不支持 long ?

原因就是 switch 對應的 JVM 字節碼 lookupswitch、tableswitch 指令只支持 int 類型

下面是 JVM 規范中的說明(https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-3.html#jvms-3.10):

The Java Virtual Machine's tableswitch and lookupswitch instructions operate only on int data. Because operations on byte, char, or short values are internally promoted to int, a switch whose expression evaluates to one of those types is compiled as though it evaluated to type int. If the chooseNear method had been written using type short, the same Java Virtual Machine instructions would have been generated as when using type int. Other numeric types must be narrowed to type int for use in a switch.

byte、char、short 類型在編譯期默認提升為 int,並使用 int 類型的字節碼指令。所以對這些類型使用 switch,其實跟 int 類型是一樣的。

為什么可以支持 String?

switch 支持 String 其實就是語法糖。編譯器會根據字符串的 hashCode 來處理。

例:

String a = "aa";
switch (a) {
  case "aa":
    System.out.println("111");
    break;
  case "AaAa":
    System.out.println("222");
    break;
  case "AaBB":
    System.out.println("333");
    break;
}

反編譯后:

String var1 = "aa";
byte var3 = -1;
switch(var1.hashCode()) { // 第一個switch,根據hashCode計算第二個switch內的位置
  case 3104:
    if (var1.equals("aa")) {
      var3 = 0;
    }
    break;
  case 2031744:
    if (var1.equals("AaBB")) {
      var3 = 2;
    } else if (var1.equals("AaAa")) {
      var3 = 1;
    }
}

switch(var3) { // 第二個switch,執行原switch的邏輯
  case 0:
    System.out.println("111");
    break;
  case 1:
    System.out.println("222");
    break;
  case 2:
    System.out.println("333");
}

可以發現,會先根據 hashCode 找出原始 switch 內的位置,再執行原代碼邏輯。

為什么用兩個 switch ?

就是為了減少編譯器的工作。

比如 switch 內有的 case 不寫 break 等復雜情況,如果想直接根據 hashCode + equals 來只生成一個 switch,編譯器就需要考慮各種情況。

所以目前編譯器只做位置映射,第二部分直接按原 switch 來生成了。

關於 lookupswitch、tableswitch 可參考:你所不知道的Java之Switch


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM