我已经读过一些JVM可以通过删除边界检查来优化代码执行。我想弄清楚的是编码技术会更好地运作。
在下面的方法 example1 中,JVM会想出来并消除 source [index] 引用的边界检查吗?
example2 更好的代码练习?看起来似乎如此,但在循环内的一些算法中,索引超出界限是正常情况。因此,您不希望在该循环中生成大量的Exception对象。
public void example1(int [] source, int index) {
if (index >= 0 && index < source.length)
System.out.println("Value is " + source[index]);
else
System.out.println("Out of range: " + index);
}
public void example2(int [] source, int index) {
try {
System.out.println("Value is " + source[index]);
} catch (IndexOutOfBoundsException exp) {
System.out.println("Out of range: " + index);
}
}
这些代码片段只是具有代表性的。我知道在这些例子中,边界检查对性能几乎不重要。但是,我正在开发一个嵌入式协议应用程序,其中冗余边界检查将加起来。
答案 0 :(得分:5)
对于你的第一个问题,在example1中,边界检查可以理论上被消除。我希望最好的现代JIT编译器能够做到这一点(例如,当扩展源[index]时,可能通过边界检查中的公共子表达式消除)。像往常一样,这将取决于实现,因此您不能依赖它。 OTOH即使没有消除边界检查,差异也将是微不足道的 - 你正在为source.length访问已经缓存的内存位置并进行一些整数比较,因此开销很小。
example2不是一个好习惯 - 你正在点击一个例外,然后抓住它并继续,好像什么也没发生。除非你仔细观察stdout,否则你可能会完全错过你的代码中存在错误的事实。
基本上有两种常见的“好”可能性取决于你认为是“索引”的有效输入:
越界索引值是 预期并被视为有效输入。在 在哪种情况下你应该测试和处理它 显式如example1。在这种情况下,您不需要抛出任何异常。
越界索引是意外的(因此是调用代码中的错误)。您的代码应在此处引发异常。如果您愿意,可以使用自己的消息捕获并重新抛出异常,但您也可以让IndexOutOfBounds异常传播。不要担心这种异常处理对性能的影响 - 你刚刚发现了一个错误,因此你希望程序尽快“大声”地失败......
答案 1 :(得分:2)
我不知道索引如何超出界限可能是正常情况。您的算法有错误,或者您没有正确验证输入。在这种情况下,验证输入包括检查索引是否在边界内。使用if
(与第一个代码段相同)进行检查显然比捕获异常更具可读性,清晰度和效率。