
An array index out-of-bounds exception is a bug class that occurs in Java when a
program tries to access an array element that does not exist.
This bug can cause your program to crash or behave unexpectedly.
To fix an array index out of bounds exception in Java, you should always ensure
that you are accessing array elements within the bounds of the array.


== Why is this an issue?

An array index out-of-bounds exception indicates a bug or a logical error in the
code.

In Java, arrays have a fixed size, and their elements are indexed starting from
`0`, counting up to the last index that is still smaller than the size.
When trying to access an array outside of this range, an
`ArrayIndexOutOfBoundsException` will be thrown and the operation will fail.

include::../impact.adoc[]

== How to fix it

=== Code examples

The following examples contain out-of-bounds accesses to arrays, resulting
in `ArrayIndexOutOfBounds` exceptions.
These situations can be avoided by carefully considering the range of valid
index values, or even better, by comparing indices against the size of a
sequence.

In this first example, the array `arr` contains three elements.
Since the first element of a list has index `0`, the last valid index is `2`.
Therefore, an `ArrayIndexOutOfBoundsException` is thrown when accessing `arr` at
index `3`.

==== Noncompliant code example

[source,java,diff-id=1,diff-type=noncompliant]
----
  void fun() {
    int[] arr = {1, 2, 3};

    int x = arr[3]; // Noncompliant: Valid indices are 0, 1 and 2
  }
----

==== Compliant solution

[source,java,diff-id=1,diff-type=compliant]
----
  void fun() {
    int[] arr = {1, 2, 3};

    int x = arr[0];
  }
----

Accessing an array with its size as the index is never correct:

==== Noncompliant code example

[source,java,diff-id=2,diff-type=noncompliant]
----
  void fun(int[] arr) {
    System.out.println(arr[arr.length]); // Noncompliant: Indexing starts at 0, hence array.length will always be an invalid index.
  }
----

==== Compliant solution

[source,java,diff-id=2,diff-type=compliant]
----
  void compliant(int[] arr) {
    // We can make sure arr is non-empty before trying to access its last element.
    if (arr.length > 0) {
      System.out.println(arr[arr.length - 1]);
    } else {
      System.out.println("Empty array!");
    }
  }
----

=== How does this work?

You should always ensure that you are accessing arrays using indices that are
within the bounds of the array.
Here are some best practices to follow:

Always compare indices against the length of an array using `if-else` statements
or other control flow constructs before accessing elements.
For this, you can use the `length` property of arrays.
For example, `arr.length` returns the length of the `arr` array.
Also, ensure that you are not accessing an array using negative indices.

Use loops to iterate over arrays instead of accessing elements directly.
This can be done using the `for` loop or the `foreach` loop.
For example, `for (int i = 0; i < arr.length; ++i)` iterates over the `arr`
array within its bounds using an index variable `i`.
The same goes for `for (Object o : arr)`.
If you manipulate the index used to access an array inside the loop, make sure
that the resulting index stays within bounds.

=== Pitfalls

The indices `0`, or `arr.length - 1` for the first and last element of an array
are not always valid!
Make sure the array in question is not empty before accessing these indices.

=== Going the extra mile

In many cases you can eliminate loops containing index-based accesses altogether
by applying the Java stream API to arrays using `java.util.Arrays.stream()`.
The API provides methods like `map()` or `filter()` that allow you to transform,
filter and perform many different operations on the elements of an array without
using indices.


== Resources

=== Documentation

* https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/ArrayIndexOutOfBoundsException.html[ArrayIndexOutOfBoundsException]
* https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Arrays.html#stream(T%5B%5D)[Javadoc for `Arrays.stream()`]
* https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/stream/Stream.html[Stream API]

=== Articles & blog posts

* A Reference Guide - https://www.baeldung.com/java-arrays-guide[Arrays in Java]

=== Standards

* https://docs.oracle.com/javase/specs/jls/se17/html/jls-10.html#jls-10.4[Array Access Specification]


ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

=== Message

Fix this access on an array element that may trigger an 'ArrayIndexOutOfBoundsException'.

'''

endif::env-github,rspecator-view[]



//=== How does this work?

//=== Pitfalls

//=== Going the extra mile

//=== Articles & blog posts
//=== Conference presentations
//=== Standards
//=== Benchmarks
