开关机箱不接受此运算符的背景是什么?
因为需要常量表达式作为其值。由于表达式不是编译时常量,因此不允许这样做。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
因此,如果该值不是常量表达式,编译器将无法使用指令将其索引到指令指针表中。case
tableswitch