web-dev-qa-db-ja.com

OR switch-caseの演算子?

次のような単純なスイッチケースを見てみましょう。

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.someValue :
        case R.id.someOtherValue:
            // do stuff
            break;
    }
}

||演算子を使用できないのはなぜですか?いいね

switch (v.getId()) {
    case R.id.someValue || R.id.someOtherValue:
        // do stuff
        break;
}

switch-caseコンストラクトはif-elseステートメントに非常に似ていますが、ifでOR演算子を使用できます。 switch-caseはこの演算子を受け入れませんか?

20
Droidman

この演算子を受け入れないスイッチケースの背景は何ですか?

caseは値として定数式を必要とするためです。 || expressionはコンパイル時定数ではないため、許可されていません。

JLSセクション14.11 から:

スイッチラベルの構文は次のとおりです。

SwitchLabel:
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命令を使用して、命令ポインターのテーブルにインデックスを付けることができません。

30
Rohit Jain

男はこのようにします

    case R.id.someValue :
    case R.id.someOtherValue :
       //do stuff

これは、2つの値の間にOR演算子を使用するのと同じです

27
spt025

||は使用できません2つのケースの間にある演算子。ただし、それらの間に区切りを使用せずに複数のケース値を使用できます。その後、プログラムはそれぞれのケースにジャンプし、「ブレーク」が見つかるまで実行するコードを探します。その結果、これらのケースは同じコードを共有します。

switch(value) 
{ 
    case 0: 
    case 1: 
        // do stuff for if case 0 || case 1 
        break; 
    // other cases 
    default: 
        break; 
}
12
Hilaj

スイッチはif-else-ifと同じではありません。

スイッチは、値に評価される式が1つあり、その値が事前定義された値のセットの1つである場合に使用されます。実行時に複数のブール演算/比較演算を実行する必要がある場合、if-else-ifを使用する必要があります。

1
Prashant Bhate