switch-case 不接受此运算符的背景是什么?
因为case
需要常量表达式作为它的值。并且由于||
表达式不是编译时常量,因此是不允许的。
从JLS 第 14.11 节:
开关标签应具有以下语法:
SwitchLabel:
案例ConstantExpression:
案例EnumConstantName:
默认:
引擎盖下:
可以从JVM Spec 第 3.10 节 - 编译开关中了解仅允许使用 case 进行常量表达式的原因:
switch 语句的编译使用tableswitch和lookupswitch指令。当切换的情况可以有效地表示为目标偏移表中的索引时,使用 tableswitch 指令。如果 switch 表达式的值超出有效索引的范围,则使用 switch 的默认目标。
因此,对于要用作tableswitch
目标偏移表的索引的案例标签,案例的值应该在编译时已知。这只有在 case 值是一个常量表达式时才有可能。并且||
表达式将在运行时评估,并且该值仅在那时可用。
从同一 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
指令将其索引到指令指针表中。