效率:切换if语句的语句

时间:2012-05-05 03:58:11

标签: java pmd

PMD告诉我

  

少于3个分支的交换机效率低,使用if语句   代替。

为什么?为什么3?他们如何定义效率?

4 个答案:

答案 0 :(得分:38)

因为switch语句是使用两个lookupswitchtableswitch的特殊JVM指令编译的。它们在处理大量案例时很有用,但是当你只有很少的分支时会导致开销。

if/else语句被编译成典型的je jne ...链,这些链更快,但在长链分支中使用时需要更多的比较。

您可以通过查看字节代码来查看差异,无论如何我都不会担心这些问题,如果有任何问题可能会成为问题,那么JIT会处理它。

实际例子:

switch (i)
{
  case 1: return "Foo";
  case 2: return "Baz";
  case 3: return "Bar";
  default: return null;
}

编译成:

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

虽然

if (i == 1)
  return "Foo";
else if (i == 2)
  return "Baz";
else if (i == 3)
  return "Bar";
else
  return null;

编译成

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

答案 1 :(得分:7)

虽然与使用if语句相比,使用交换机时效率较低,但在大多数情况下,这些增益可以忽略不计。任何有价值的源代码扫描程序都会认识到micro-optimizations是代码清晰度的第二位。

他们说如果交换机非常短,if语句既易于阅读又占用的代码行少于switch语句。

来自PMD website

  

TooFewBranchesForASwitchStatement:转换语句被用于支持复杂的分支行为。仅在少数情况下使用开关是不明智的,因为开关不像if-then语句那么容易理解。在这些情况下,使用if-then语句来提高代码可读性。

答案 2 :(得分:6)

  

为什么?

当代码(最终)由JIT编译器编译为本机代码时,使用不同的指令序列。交换机由执行间接分支的一系列本机指令实现。 (该序列通常从表中加载一个地址,然后分支到该地址。)if / else是一个实现为指令,用于评估条件(可能是比较指令),后跟条件分支指令。

  

为什么3?

这是一个经验观察,我假设基于分析生成的本机代码指令和/或基准测试。 (或者可能不是。为了绝对肯定,你需要询问PMD规则的作者如何得出这个数字。)

  

他们如何定义效率?

执行指令所需的时间。


我个人对此规则有所疑问......或者更准确地说是对此消息的问题。我认为它应该说if / else语句比具有2个案例的开关更简单,更易读。效率问题是次要问题,可能无关紧要。

答案 3 :(得分:1)

我认为这与交换机和if / else编译方式有关。

假设需要5次计算来处理switch语句。假设if语句需要两次计算。交换机中少于3个选项等于ifs中的4个计算与交换机中的5个计算。但是,开关中的开销保持不变,因此如果它有3个选择,ifs将是3 * 2处理,而5仍然是交换机。

查看数百万次计算时的收益极其微不足道。更多的是“这是更好的方式”,而不是任何可能影响你的事情。它只能在相当于迭代的情况下循环使用该函数数百万次。