-1

I'm getting periodic crash reports on the following line of code:

myList.get(myList.size() - 1)

Which wouldn't be that interesting if not for the stack trace:

java.lang.ArrayIndexOutOfBoundsException: length=22; index=-1
java.util.ArrayList.get ArrayList.java:439
com.myapp.ope.api.ApiManager$2.onResponse ApiManager.java:215
retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1.lambda$onResponse$0$DefaultCallAdapterFactory$ExecutorCallbackCall$1 DefaultCallAdapterFactory.java:89
retrofit2.-$$Lambda$DefaultCallAdapterFactory$ExecutorCallbackCall$1$hVGjmafRi6VitDIrPNdoFizVAdk.run Unknown Source:6

Which seems to imply myList has a length of 22. So how is the index calculated at -1 (which means .size() would have reported 0)?

Adam Johns
  • 35,397
  • 25
  • 123
  • 176
  • So yes, the list's size is 0, it has 0 items within it, and you're trying to get the item at index -1, which obviously won't work. I've not seen the term "length" in this error message context before and am not sure what it means, but it doesn't change the salient facts about what caused your error. – Hovercraft Full Of Eels Nov 17 '21 at 19:38
  • @HovercraftFullOfEels, Ah. So "length" in this context doesn't mean size, I see. I assumed it did mean size and somehow the size was changing between the .size() call and the .get() call. – Adam Johns Nov 17 '21 at 19:42
  • An ArrayList doesn't really have a "length" (that I know of). It has a *capacity*, which is the length of its backing array, the items of which some may be null, and a size, how many actual objects it holds. The size is all that really matters here. – Hovercraft Full Of Eels Nov 17 '21 at 19:43
  • I mean, it pretty clearly means, in the context of this error message, the length of the internal array the `ArrayList` is using as storage. – Louis Wasserman Nov 17 '21 at 19:44
  • @LouisWasserman, so how is the internal array length 22 while the .size is reported as 0 on the same line? – Adam Johns Nov 17 '21 at 19:46
  • Please check out: [Initial size for the ArrayList](https://stackoverflow.com/questions/8896758/initial-size-for-the-arraylist) – Hovercraft Full Of Eels Nov 17 '21 at 19:47
  • That's perfectly normal. `size` is the number of elements actually there, the amount of the array actually being used. The array is _normally_ oversized. – Louis Wasserman Nov 17 '21 at 19:47
  • You can always check `ArrayList.java` to see how the error message is generated. Is the `22` in the error message refers to the same variable as would `size` method? – TeWu Nov 17 '21 at 20:17

2 Answers2

3

The ArrayList in Java 8 only checks if the index is greater than its size, throwing an IndexOutOfBoundsException if so. Otherwise array[index] is used to access the desired element of the array used to store the list elements. This will throw an ArrayIndexOutOfBoundsException if the index is out of range, using the length of the array in the message. The array will be substituted by larger one if needed, but it will never be changed to a smaller one - so it is normal that the array is larger than required.

In Java 9, the index check was changed: it uses Objects.checkIndex(), which checks both limits and uses the size of the list for the Exception message.

user16320675
  • 135
  • 1
  • 3
  • 9
1

ArrayList is backed by an array internally and it dynamically adjusts internal array as needed and size variable is maintained as you add elements ( increments as you add elements and decrements as you delete elements).

say at some point underlying array of ArrayList is with the length 22 (could be empty array, i.e. no elements stored), when you try to access it with -1 index, it will throw the java.lang.ArrayIndexOutOfBoundsException

*try printing list size before accessing the list as well to see if the size is coming as 0 or not

Janardhan
  • 89
  • 3