如果看过 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
,即强制内联。
Reference
JDK 9 intrinsics · GitHub
Difference between “native” keyword and @HotSpotIntrinsicCandidate annotation - Stack Overflow