What you'll learn
Quick Answer
ArrayIndexOutOfBoundsException means you used an index that is negative or greater than or equal to the array's length. Valid indices run from 0 to length minus 1, so a five-element array has no index 5. The usual causes are a loop written with <= instead of <, an index returned as -1 by a failed search, and a split or input that produced fewer elements than you expected. The exception message names the offending index directly.
What the message actually tells you
Java arrays are zero-based and fixed-length. An array created with five slots has indices 0, 1, 2, 3 and 4. There is no index 5, and asking for it throws at runtime rather than at compile time, because the index is usually a variable the compiler cannot evaluate.
int[] marks = {88, 91, 76, 64, 95};
for (int i = 0; i <= marks.length; i++) {
System.out.println(marks[i]);
}
// 88 91 76 64 95
// Exception in thread "main"
// java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5Modern JDKs print both numbers, which is generous. Index 5 is what you asked for, length 5 is what exists, and the highest legal index is therefore 4. Older JDKs printed only the index, so if you are on an ancient runtime you get a bare number and have to find the length yourself.
Two variants are worth recognising immediately. Index -1 out of bounds almost never comes from a loop; it comes from a search method that returned -1 to mean not found and you used the result without checking. And if the message says StringIndexOutOfBoundsException instead, you are indexing a String with charAt, not an array, so look at your string handling rather than your array.
Also note where the stack trace points. The top frame is the line that did the indexing. If that line is inside a helper method, the frame below it tells you which caller supplied the bad value, and that is usually where the real fix belongs.
The off-by-one loop, and why it survives testing
The single commonest cause is a loop condition using <= where it should use <. Because indices start at 0, a loop over an array of length n must stop before n.
// wrong: runs i = 0..5, six iterations over five slots
for (int i = 0; i <= marks.length; i++)
// right: runs i = 0..4
for (int i = 0; i < marks.length; i++)
// also right, when you deliberately look ahead one place
for (int i = 0; i < marks.length - 1; i++)
System.out.println(marks[i] + marks[i + 1]);That third form is the one people get wrong in the other direction. Any loop body that touches arr[i + 1] must stop at length - 1, and any body that touches arr[i - 1] must start at 1. Writing the loop bound and the loop body at different times is how these drift apart.
The reason this survives casual testing is that the exception is thrown on the last iteration, after the correct output has already been printed. A quick glance at the console shows all five marks and looks fine, and the stack trace at the bottom gets ignored. Whenever a program produces the right output and then crashes, suspect a bound.
If the loop does not need the index at all, remove the possibility entirely with the enhanced for loop. It cannot go out of bounds because there is no index to get wrong:
for (int m : marks) {
System.out.println(m);
}Use the indexed form only when you genuinely need i, for example to write back into the array or to compare neighbouring elements.
length, length() and size() are three different things
Java uses three different spellings for the same idea, and mixing them up produces a compiler error that names the wrong problem.
int[] marks = {88, 91, 76};
String city = "Pune";
List<String> names = new ArrayList<>();
marks.length // field, no brackets -> 3
city.length() // method, brackets -> 4
names.size() // method on List -> 0Write marks.length() and the compiler says cannot find symbol, pointing at length(). Write city.length and it says cannot find symbol as well. Neither message mentions arrays or strings usefully, so the first time you meet it the wording is more confusing than it needs to be. The rule to memorise: arrays have a field, everything else has a method.
The same confusion causes genuine bounds bugs when converting between types. A common one is looping over a String as if it were an array:
String city = "Pune";
for (int i = 0; i <= city.length(); i++) {
System.out.println(city.charAt(i));
}
// StringIndexOutOfBoundsException at i = 4Note the different exception type. String is not an array, so it throws StringIndexOutOfBoundsException, which is a sibling class. The cause and the fix are identical, but if you search only for the array version you will not find the answer.
For 2D arrays there are two lengths and they are not interchangeable. grid.length is the number of rows and grid[r].length is the width of that particular row. Java allows jagged arrays where rows have different widths, so a nested loop must read the inner length from the row it is currently on, not from row zero.
The quiet sources: split, indexOf and user input
Loops are the obvious cause. The bugs that reach production come from data that is a different shape than you assumed.
split() drops trailing empty fields. This one surprises almost everybody:
String line = "Asha,";
String[] parts = line.split(",");
System.out.println(parts.length); // 1, not 2
System.out.println(parts[1]); // Index 1 out of bounds for length 1With the default single-argument form, Java removes trailing empty strings from the result. A CSV row whose last column is blank therefore produces a shorter array than the header suggests. Pass a negative limit, line.split(",", -1), to keep them, and check parts.length before indexing either way.
indexOf returns -1 when nothing matches. Using that value directly is what produces the negative-index message:
String[] cities = {"Pune", "Chennai", "Jaipur"};
int pos = Arrays.asList(cities).indexOf("Kochi"); // -1
System.out.println(cities[pos]);
// Index -1 out of bounds for length 3Always test if (pos >= 0) before using a search result as an index. The same applies to String.indexOf, which returns -1 for a substring that is not present and is then commonly fed straight into substring.
Input sized by the user. Reading a count with Scanner and then reading that many values assumes the count is honest. If the user types 5 and supplies 3 values, or if you allocate new int[n] from a value read after a stray newline, the array and the loop disagree. Validate the count before allocating, and remember that a negative count throws NegativeArraySizeException at allocation time, which is a different exception with a different fix.
How to debug a bounds error in two minutes
The exception already tells you the bad index and the real length, so the only unknown is which variable produced that index. Print both at the top of the loop body:
for (int i = 0; i < marks.length; i++) {
System.out.println("i=" + i + " length=" + marks.length);
System.out.println(marks[i]);
}If the printed length is 0, the array was never populated and the bug is in whatever was supposed to fill it. An uninitialised array of objects is a different trap: new String[3] gives you three null slots, so the length is 3 but touching arr[0].length() throws NullPointerException instead. Length and contents are separate questions.
Arrays.toString(marks) prints the whole array in one line and is far more useful than printing elements individually, because it shows you at a glance whether the data is the shape you expected. For 2D arrays use Arrays.deepToString(grid).
Do not catch the exception to make it go away:
// don't do this
try {
process(marks);
} catch (ArrayIndexOutOfBoundsException e) {
// ignored
}An ArrayIndexOutOfBoundsException is not an expected runtime condition like a missing file. It is a logic error in your own code, and catching it means shipping code that computes a wrong index and then pretends it did not. Fix the bound instead.
Finally, if the array is being resized, appended to or searched, an ArrayList is usually the better structure. Its add grows automatically, its size() is always accurate, and out-of-range access throws IndexOutOfBoundsException with the same clarity but far fewer chances to get the bookkeeping wrong. Interviewers will still ask you to reason about raw arrays, so learn both, but reach for the collection in real code.
