开关盒中的OR运算符?

Dro*_*man 21 java switch-statement

我们来看一个简单的开关盒,看起来像:

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

我想知道为什么不允许使用||运营商?喜欢

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

switch-case构造非常类似于if-else语句,但您可以使用OR运算符if.switch-case不接受此运营商的背景是​​什么?

Roh*_*ain 30

交换机箱不接受此运营商的背景是什么?

因为case需要常量表达作为其值.由于||表达式不是编译时常量,因此不允许.

来自JLS第14.11节:

切换标签应具有以下语法:

SwitchLabel:
case ConstantExpression:
case EnumConstantName:
default:


引擎盖下:

JVM Spec Section 3.10 - 编译开关可以理解允许仅使用case进行常量表达的原因:

switch语句的编译使用tableswitchlookupswitch指令.当交换机的情况可以有效地表示为目标偏移表中的索引时,使用tableswitch指令.如果开关表达式的值超出有效索引的范围,则使用开关的默认目标.

因此,对于要tableswitch作为目标偏移表的索引使用的案例标签,应在编译时知道案例的值.只有在案例值是常量表达式时才有可能.而||表达在运行时进行评估,并且该值将只能在那个时候.

从同一JVM部分,以下内容switch-case:

switch (i) {
    case 0:  return  0;
    case 1:  return  1;
    case 2:  return  2;
    default: return -1;
}
Run Code Online (Sandbox Code Playgroud)

编译为:

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
Run Code Online (Sandbox Code Playgroud)

因此,如果该case值不是常量表达式,则编译器将无法使用tableswitch指令将其索引到指令表的表中.

  • 我觉得提问者知道这一点,但是想知道为什么这个限制开始了. (2认同)
  • @Maver1ck“由于表达式不是编译时常量,因此是不允许的。” 因此,在许多情况下,它可以通过更简单的编译器优化来更快地执行。由于低级技巧和魔法,它比 if 语句更快。 (2认同)

spt*_*025 29

老兄喜欢这样

    case R.id.someValue :
    case R.id.someOtherValue :
       //do stuff
Run Code Online (Sandbox Code Playgroud)

这与在两个值之间使用OR运算符相同由于这种情况,运算符不在切换情况下

  • 这个答案不再适用于这个问题了.OP表达得非常糟糕.根据评论,OP非常清楚这一点.我建议删除这个"答案". (6认同)
  • 嘿@BalusC这个答案实际上对我的申请有帮助,所以我建议保留这个“答案” (2认同)

Hil*_*laj 13

你不能使用|| 运营商介于2个案例之间.但是您可以使用多个案例值而不使用它们之间的中断.然后程序将跳转到相应的情况,然后它将查找要执行的代码,直到找到"中断".因此,这些案例将共享相同的代码.

switch(value) 
{ 
    case 0: 
    case 1: 
        // do stuff for if case 0 || case 1 
        break; 
    // other cases 
    default: 
        break; 
}
Run Code Online (Sandbox Code Playgroud)

  • 或者你也可以这样使用 case 0, 1: //if the case 0 || 1 (2认同)