最近我碰到了静态代码分析工具(PMD)抱怨switch
语句分支太少的情况。它建议把它变成一个if语句,我不想做,因为我知道很快会添加更多案例。但我想知道javac
是否执行了这样的优化。我使用JAD反编译代码,但它仍然显示了一个开关。这可能是JIT优化的运行时吗?
更新:请不要被我的问题背景误导。我不是在询问PMD,我不是在询问是否需要微优化等等。问题显然只有这个:当前(Oracle 1.6.x)JVM实现是否包含一个处理交换机的JIT很少有分支机构。
答案 0 :(得分:2)
确定JIT编译器如何优化switch语句的方法是:
请注意,与所有与性能和优化相关的问题一样,答案取决于硬件平台和JVM供应商和版本。
参考:Disassemble Java JIT compiled native bytecode
如果这个问题“只是空闲的好奇心”,那就这样吧。
但是,还应该指出,出于性能原因重写代码以使用switch
或if
可能是一个坏主意和/或浪费时间。
这可能是浪费时间,因为原始版本和手动优化版本之间的时间差异(如果有的话)可能是微不足道的。
这是一个坏主意,因为您的优化可能仅对特定硬件和JVM组合有帮助。在其他方面,它可能没有效果......甚至是反优化。
简而言之,即使你知道JIT优化器如何处理这个问题,你也许不应该在编程中考虑它。
(当然例外是当你有一个真正可测量的性能问题,并且分析指向(比方说)一个3分支switch
作为瓶颈之一。)
答案 1 :(得分:1)
如果你在调试模式下编译它,通常在你反编译它时,你仍然可以得到开关。否则,任何调试尝试都会遗漏某些信息,例如行号和原始指令流 因此,您可以尝试在生产模式下进行编译,看看反编译结果是什么。
然而,switch语句,特别是如果预计会增长,通常被认为是代码气味,应该被评估为重构的良好候选者。
答案 2 :(得分:1)
至于你澄清问题是什么之后。
由于这对硬件和JVM造成如此强烈的影响(使用Java商标的JVM可能由Oracle以外的公司开发,只要它们遵守JVM规范).Id说唯一有效的方法是进行速度测试
剪出一大块代码,将其锁定在循环中进行大量重复,检查循环执行前后的时间。重复两种解决方案(切换和if)
这可能看似简单和愚蠢,但它确实有效,并且比反编译,读取字节码和内存转储等快得多。
您必须记住,Java实际上使用的是虚拟机和字节码。我很确定这一切都得到了处理和优化。我们正在使用高级语言来避免您要求的微观管理和优化
更一般地说,我认为你试图过早地优化一下。如果你知道那个开关中会有更多的情况,为什么呢?你有没有运行过探查器?如果没有,它没有用优化。 “过早优化是所有邪恶的根源”。您可能正在优化实际上不是瓶颈的代码的一部分,增加代码复杂性并浪费您自己的时间来编写无任何贡献的代码。
我不知道你正在制作什么类型的应用程序,但经验法则说清晰度是王道,你通常应该选择更简单,更优雅,自我记录的解决方案。
答案 3 :(得分:0)
javac的表现几乎没有优化。所有优化都在运行时使用JIT执行。除非你知道你有性能问题,否则我认为你没有。
PMD抱怨的是清晰度。 e.g。
if (a == 5) {
// something
} else {
// something else
}
比
更清晰switch(a) {
case 5:
// something
break;
default:
// something else
break;
}