如果看过 JDK 8 中 ArrayList 的源码,你会发现存在如下代码 ArrayList.java at jdk8-b120:
1 | /** |
令我不解的是为何此处不对负数索引进行检查,有部分观点认为这是一项微优化,即负数肯定会触发异常,所以不必进行检查,但是我并不太理解该说法,因为只要越界,底层都会抛出异常,那么 rangeCheck 方法还有存在的必要吗?如果我们编写如下代码:
1 | import java.util.ArrayList; |
你会发现输出如下:
1 | java.lang.ArrayIndexOutOfBoundsException: -1 |
以上的异常信息让人困惑,都是越界,但是异常类型却不一样,虽然 ArrayIndexOutOfBoundsException 是 IndexOutOfBoundsException 的子类。如果查看 ArrayList 类中的 rangeCheckForAdd 方法,你会发现实现如下 ArrayList.java at jdk8-b120:
1 | /** |
此处对索引为负数的情况进行了检查,关于这块逻辑我也无法解释,我更相信这些方法是由不同开发人员编写,如果查看 java.util.Arrays.ArrayList 的源码,你会发现根本不存在范围检查。
在查询代码提交记录后我发现在 JDK 9 中 rangeCheck 方法已经修改为了支持检查负数索引的实现,这次提交可参考:8079136: Accessing a nested sublist leads to StackOverflowError · openjdk/jdk@763f489 · GitHub,且调用的参数检查方法 checkIndex 被标记了 @ForceInline,即强制内联。
References
JDK 9 intrinsics · GitHub
Difference between “native” keyword and @HotSpotIntrinsicCandidate annotation - Stack Overflow