或开关盒中的操作员?

2022-08-31 17:23:47

让我们看一个简单的开关案例,如下所示:

@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;
}

该构造与语句非常相似,但是可以在其中使用 OR 运算符。不接受此运算符的背景是什么?switch-caseif-elseifswitch-case


答案 1

伙计做这个

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

这与在两个值之间使用 OR 运算符相同,因为在这种情况下,运算符在开关案例中不存在


答案 2

开关机箱不接受此运算符的背景是什么?

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

来自 JLS 第 14.11 节

开关标签应具有以下语法:

SwitchLabel:
case ConstantExpression :
case EnumConstantName :
default :


在引擎盖下:

允许使用 case 的常量表达式背后的原因可以从 JVM 规范第 3.10 节 - 编译交换机中理解:

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

因此,对于要用作目标偏移量表的索引的 cases 标签,应在编译时知道 case 的值。仅当大小写值是常量表达式时,才有可能。表达式将在运行时计算,并且该值仅在那时可用。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

因此,如果该值不是常量表达式,编译器将无法使用指令将其索引到指令指针表中。casetableswitch