Jac*_*ack 38
由于switch语句编译有两个特殊的JVM指令是lookupswitch和tableswitch.它们在处理大量案例时很有用,但是当你只有很少的分支时会导致开销.
一个if/else声明,而不是被编译成典型je jne...链,其速度更快,但在分支的长链时需要更多的比较.
您可以通过查看字节代码来查看差异,在任何情况下我都不会担心这些问题,如果有任何问题可能会成为问题,那么JIT会处理它.
实际例子:
switch (i)
{
case 1: return "Foo";
case 2: return "Baz";
case 3: return "Bar";
default: return null;
}
Run Code Online (Sandbox Code Playgroud)
编译成:
L0
LINENUMBER 21 L0
ILOAD 1
TABLESWITCH
1: L1
2: L2
3: L3
default: L4
L1
LINENUMBER 23 L1
FRAME SAME
LDC "Foo"
ARETURN
L2
LINENUMBER 24 L2
FRAME SAME
LDC "Baz"
ARETURN
L3
LINENUMBER 25 L3
FRAME SAME
LDC "Bar"
ARETURN
L4
LINENUMBER 26 L4
FRAME SAME
ACONST_NULL
ARETURN
Run Code Online (Sandbox Code Playgroud)
而
if (i == 1)
return "Foo";
else if (i == 2)
return "Baz";
else if (i == 3)
return "Bar";
else
return null;
Run Code Online (Sandbox Code Playgroud)
编译成
L0
LINENUMBER 21 L0
ILOAD 1
ICONST_1
IF_ICMPNE L1
L2
LINENUMBER 22 L2
LDC "Foo"
ARETURN
L1
LINENUMBER 23 L1
FRAME SAME
ILOAD 1
ICONST_2
IF_ICMPNE L3
L4
LINENUMBER 24 L4
LDC "Baz"
ARETURN
L3
LINENUMBER 25 L3
FRAME SAME
ILOAD 1
ICONST_3
IF_ICMPNE L5
L6
LINENUMBER 26 L6
LDC "Bar"
ARETURN
L5
LINENUMBER 28 L5
FRAME SAME
ACONST_NULL
ARETURN
Run Code Online (Sandbox Code Playgroud)
虽然与使用if语句相比,使用交换机时效率会略有提高,但在大多数情况下,这些增益可以忽略不计.任何有价值的源代码扫描程序都会认识到微优化是代码清晰度的次要因素.
他们说如果交换机非常短,if语句既易于阅读又占用的代码行少于switch语句.
来自PMD网站:
TooFewBranchesForASwitchStatement:Switch语句被用于支持复杂的分支行为.仅在少数情况下使用开关是不明智的,因为开关不像if-then语句那么容易理解.在这些情况下,使用if-then语句来提高代码可读性.
这是为什么?
当代码(最终)由JIT编译器编译为本机代码时,使用不同的指令序列.交换机由执行间接分支的一系列本机指令实现.(该序列通常从表中加载一个地址,然后分支到该地址.)if/else是一个实现为指令,用于评估条件(可能是比较指令)后跟条件分支指令.
为什么3?
这是一个经验观察,我假设基于分析生成的本机代码指令和/或基准测试.(或者可能不是.为了绝对肯定,你需要询问PMD规则的作者如何得出这个数字.)
他们如何定义效率?
执行指令所需的时间.
我个人会对这个规则提出异议......或者更准确地说是对这个消息的问题.我认为它应该说if / else声明比具有2种情况的开关更简单,更易读.效率问题是次要问题,可能无关紧要.
| 归档时间: |
|
| 查看次数: |
2346 次 |
| 最近记录: |