為什麼在Java 8的Integer包裝器切換中,為什麼不能編譯'char'大小寫,但是當切換到Byte時編譯就可以了?



java-8 switch-statement (1)

無法編譯:

void test(Integer x){
      switch(x){
       case 'a':
      }
}

編譯OK:

void test(Byte x){
      switch(x){
       case 'a':
      }
}

原因很複雜,但是原因全在Java語言規範的細節中(如果需要,可以 打印精美 )。

首先, JLS 14.11 switch 語句進行了以下說明:

“與switch語句關聯的每種情況常量都必須在分配方面與switch語句的Expression(第 §5.2 )的類型兼容。”

這意味著 'a' 需要分別分配給 IntegerByte

但這聽起來不對:

  • 您會認為 ,由於 應將 'a' 分配給 Integer 因為 char > int 分配是合法的。 (任何 char 值都適合 int 。)

  • 您會認為 ,由於 不應 'a' 分配給 Byte 因為 char > byte 分配不合法。 (大多數 char 值不適合一個字節。)

實際上,這些都不是正確的。 要理解原因,我們需要閱讀有關分配上下文中允許的內容的 §5.2 實際內容。

“分配上下文允許使用 以下其中一項

  • 身份轉換(第5.1.1節)
  • 不斷擴大的原始轉換(第5.1.2節)
  • 擴展參考轉換(第5.1.5節)
  • 擴大參考轉換,然後進行拆箱轉換
  • 擴展參考轉換,然後進行拆箱轉換,然後進行擴展原語轉換
  • 拳擊轉換(第5.1.7節)
  • 裝箱轉換,然後擴大參考轉換
  • 拆箱轉換(第5.1.8節)
  • 取消裝箱轉換,然後進行擴大的原始轉換。”

要從 'a'Integer ,我們需要將 char 1 擴展為 int 然後將 int 裝箱為 Integer 。 但是,如果您查看允許的轉換組合,則無法進行加寬原始轉換和裝箱轉換。

因此,不允許對 Integer 'a' 。 這解釋了第一種情況下的編譯錯誤。

您會認為不允許將 'a'Byte ,因為這將涉及原始的縮小轉換...根本不在列表中。 實際上,文字是一種特殊情況。 §5.2 繼續說以下內容。

“此外,如果該表達式是類型為byte,short,char或int的常量表達式(第 §15.28 ):

  • 如果變量的類型為byte,short或char,並且常量表達式的值可以表示為變量的類型,則可以使用縮窄的原始轉換。

  • 如果變量的類型為 ByteShortCharacter ,並且常量表達式的值分別可以用byte,short或char類型表示,則可以使用緊縮原始轉換後跟裝箱轉換。

其中的第二個適用於 Byte 'a' ,因為:

  • 字符文字是一個常量表達式,並且
  • 'a' 的值是 97 十進制數,該值在 byte 範圍內( -128+127 )。

這解釋了為什麼第二個示例中沒有編譯錯誤。

1-我們不能將 'a'Character ,然後再將 Character 擴展到 Integer 因為 Character 不是Java的 Integer 子類型。 如果源類型是目標類型的子類型,則只能使用加寬引用轉換。





switch-statement