switch-case がこの演算子を受け入れない背景は何ですか?
case
値として定数式が必要なためです。また、||
式はコンパイル時の定数ではないため、使用できません。
JLSセクション14.11から:
スイッチ ラベルの構文は次のとおりです。
SwitchLabel:
case ConstantExpression:
case EnumConstantName:
デフォルト:
フードの下:
ケース付きの定数式のみを許可する理由は、JVM Spec Section 3.10 - Compiling Switchesから理解できます。
switch ステートメントのコンパイルでは、tableswitchおよびlookupswitch命令を使用します。tableswitch 命令は、スイッチのケースがターゲット オフセットのテーブルへのインデックスとして効率的に表現できる場合に使用されます。スイッチの式の値が有効なインデックスの範囲外にある場合、スイッチのデフォルトのターゲットが使用されます。
そのため、ケース ラベルをtableswitch
ターゲット オフセットのテーブルへのインデックスとして使用するには、ケースの値がコンパイル時にわかっている必要があります。これは、ケース値が定数式である場合にのみ可能です。式は実行時に評価され、||
値はその時点でのみ使用可能になります。
同じ JVM セクションから、次のようになりますswitch-case
。
switch (i) {
case 0: return 0;
case 1: return 1;
case 2: return 2;
default: return -1;
}
次のようにコンパイルされます。
0 iload_1 // Push local variable 1 (argument i)
1 tableswitch 0 to 2: // Valid indices are 0 through 2 (NOTICE This instruction?)
0: 28 // If i is 0, continue at 28
1: 30 // If i is 1, continue at 30
2: 32 // If i is 2, continue at 32
default:34 // Otherwise, continue at 34
28 iconst_0 // i was 0; push int constant 0...
29 ireturn // ...and return it
30 iconst_1 // i was 1; push int constant 1...
31 ireturn // ...and return it
32 iconst_2 // i was 2; push int constant 2...
33 ireturn // ...and return it
34 iconst_m1 // otherwise push int constant -1...
35 ireturn // ...and return it
そのため、case
値が定数式でない場合、コンパイラは命令を使用して命令ポインタのテーブルにインデックスを付けることができませんtableswitch
。