/**
* Checks if the given index is in range. If not, throws an appropriate
* runtime exception. This method does *not* check if the index is
* negative: It is always used immediately prior to an array access,
* which throws an ArrayIndexOutOfBoundsException if index is negative.
*/
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
From: jdk/ArrayList.java at jdk8-b120 · openjdk/jdk · GitHub
If we write the following code, both indexes are out of bounds, but the exception types are different.
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("");
try {
list.get(-1);
} catch (Exception e) {
e.printStackTrace();
}
try {
list.get(1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
The output is as follows:
java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.ArrayList.elementData(ArrayList.java:424)
at java.util.ArrayList.get(ArrayList.java:437)
at Test.main(Test.java:11)
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.rangeCheck(ArrayList.java:659)
at java.util.ArrayList.get(ArrayList.java:435)
at Test.main(Test.java:17)
Related question:
rangeCheckForAdd
method in the java.util.ArrayList
check for negative index?java.util.Arrays.ArrayList
do index out-of-bounds checking?What confuses me is why their implementations are inconsistent? Are these methods written by different people with their own programming style? In other words, if out-of-bounds exceptions will eventually fire, then there is no need to check.
It's a micro-optimization. For code clarity you might prefer the same exception for both, but when you're in a hot loop you'll want to avoid an unnecessary operation. ArrayList
being an old class, the effect this has may have varied between times and JDK versions. If someone has enough interest they could benchmark it with 1.8 and newer JDKs to see how much of an optimization it is for get()
.
Since accessing a negative array index will fail anyway, there is no need to check for it. However the size of the ArrayList
is not always the same as the size of its internal array, so it needs to be checked explicitly.
As to why rangeCheckForAdd
does check for negative indexes, good question. Adding is slow anyway, so the micro-optimization wouldn't make much of a difference. Maybe they wanted consistent error messaging here.