整数ラッパーを介したJavaスイッチで、「char」のケースがコンパイルされないのはなぜですか?スイッチがバイトを超えている場合、コンパイルは問題ありませんか?


18

コンパイルしません:

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

コンパイルOK:

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

1
整数は4バイトで、charは2バイトです。したがって、最初のケースでは、どの文字を書いても、整数より小さくなります。ただし、2番目のケースでは、書き込んだ文字が最大バイトよりも大きくなる可能性があるため、そのケースは実行されません。
ヤロスワフPawlak

その説明は間違っています。実際、第2の例では、内のコード'a'の場合は、あろう場合に実行されるxバイトです97。(私を信じないなら、試してください。)実際の説明については、私の答えを参照してください。
Stephen C

回答:


19

理由はかなり複雑ですが、すべてJava言語仕様の詳細(必要に応じて詳細に印刷)にあります。

まず、JLS 14.11switchステートメントについて次のように述べています。

「switchステートメントに関連付けられているすべてのcase定数は、switchステートメントの式のタイプと互換性のある代入でなければなりません(§5.2)。」

これは、とに それぞれ'a'割り当て可能である必要があることを意味します。IntegerByte

しかし、それは正しく聞こえません:

  • ->の 割り当ては合法であるため、それ以降'a' forに割り当て可能であると考えるでしょう。(すべての値がに収まります。)Integercharintcharint

  • あなたは思うだろうので、ということ'a' すべきではないに割り当てByte理由char> - byte 割り当ては法的ではありません。(ほとんどのchar値は1バイトに収まりません。)

実際、どちらも正しくありません。理由を理解するには、割り当てコンテキストで許可されている内容について、実際にJLS 5.2を読む必要があります。

「割り当てコンテキストでは、次いずれかを使用できます

  • アイデンティティ変換(§5.1.1)
  • 拡大プリミティブ変換(§5.1.2)
  • 拡大する参照変換(§5.1.5)
  • 拡張参照変換とそれに続くボックス化解除変換
  • 拡張参照変換とそれに続くボックス化解除変換、その後の拡張プリミティブ変換
  • ボクシング変換(§5.1.7)
  • ボクシング変換とそれに続く拡大参照変換
  • ボックス化解除変換(§5.1.8)
  • ボックス化解除変換とそれに続くプリミティブ変換の拡大。」

行くために'a'するIntegerために、我々は、必要があるだろう1は広げるcharの値をint、ボックスintInteger。ただし、許可されている変換の組み合わせを見ると、拡大プリミティブ変換の後にボックス化変換を行うことはできません。

したがって'a'Integer許可されていません。これは、最初のケースのコンパイルエラーを説明します。

'a'to Byteは原始的なナローイング変換を伴うため、許可されていないと思われるかもしれません...これはリストにはまったくありません。実際、リテラルは特殊なケースです。 JLS 5.2ではさらに次のように述べています。

「さらに、式がバイト、ショート、char、またはint型の定数式(§15.28)の場合:

  • 変数がバイト型、ショート型、または文字型であり、定数式の値が変数の型で表現できる場合、ナローイングプリミティブ変換を使用できます。

  • 変数は、型の場合ボクシング変換続い狭くプリミティブ変換を使用することができるByteShortまたはCharacter、及び定数式の値が、それぞれのタイプのバイト、短い、またはcharで表現可能です。」

これらの第二は、に適用される'a'Byte、理由は次のとおりです。

  • 文字リテラルは定数式であり、
  • の値'a'9710進数で、byte-128+127)の範囲内です。

これは、2番目の例にコンパイルエラーがない理由を説明しています。


1- はJavaののサブタイプではないため'a'、aにボックス化してCharacterから拡大CharacterするIntegerことCharacterはできませんInteger。ソースタイプがターゲットタイプのサブタイプである場合にのみ、拡大参照変換を使用できます。


intスイッチタイプとして使用できますか?(char -> int許可されているプリミティブな拡張であるため)
AjahnCharles
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.