The java.lang.IndexOutOfBoundsException
in Java is thrown when an index used in arrays, lists, or strings is not valid. A valid index must be a number from 0 up to one less than the total number of items. For example, in a list of 3 items, the valid indices are 0, 1, and 2.
Here’s a quick example:
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
int element = list.get(3); // This will throw IndexOutOfBoundsException
The error message you’d get would look something like this:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
Here are some other common ways the IndexOutOfBoundsException might be thrown:
- Sublist Operations: When creating a sublist from a larger list, if the start or end index is out of bounds. For example,
list.subList(-1, 3) or list.subList(2, 10)
where the list size is less than 10. - String Manipulation Methods: Beyond just accessing characters, methods like
substring
,charAt
, andsplit
can throw this exception if the indices provided are out of range. - Vector or Stack: Other data structures in the Java Collections Framework like Vector and Stack can also throw this exception when trying to access elements with an invalid index.
- Custom Data Structures: Developers can implement custom data structures that use indexing, and they may throw IndexOutOfBoundsException to indicate misuse, such as accessing elements not present in the structure.
You may also see StringIndexOutOfBoundsException and ArrayIndexOutOfBoundsException, which are more specific subtypes of the IndexOutOfBoundsException, indicating out-of-bounds conditions for strings and arrays, respectively.
How to Fix java.lang.IndexOutOfBoundsException
Fixing an IndexOutOfBoundsException depends on the situation that led to it. Let’s look at some typical problem scenarios and how to fix each.
Sublist Operations
Scenario: You created a sublist with invalid indices.
List<Integer> list = Arrays.asList(1, 2, 3, 4);
List<Integer> sublist = list.subList(2, 5);
Fix: Ensure that the indices for subList are within the valid range of the original list.
List<Integer> sublist = list.subList(2, 4); // Correct end index to 4
The reason list.subList(2, 4)
works correctly is that it specifies a valid segment of the list where the starting index is 2 (the third item, 3) and the ending index is 4 (just beyond the fourth item, 4). This operation does not go out of bounds since the original list has elements at indices 0, 1, 2, and 3. Thus, a request for indices 2 to 3 (inclusive of 2 and exclusive of 4) is valid.
String Manipulation Methods
Scenario: You’re accessing characters or substrings with invalid indices. For example:
String str = "hello";
char ch = str.charAt(5);
Fix: Adjust the index to be within the valid range.
char ch = str.charAt(4); // Use the highest valid index
Vector or Stack
Scenario: You’re accessing elements from a Vector or Stack with an invalid index.
Stack<Integer> stack = new Stack<>();
stack.push(1);
int num = stack.get(1);
Fix: Use methods that check if the stack is empty or ensure indices are within range.
if (!stack.isEmpty()) {
int num = stack.get(0); // Access the first element safely
}
Custom Data Structures
Scenario: You’re accessing elements in a custom data structure without bounds checks.
public class SimpleArrayWrapper {
private int[] elements;
// Constructor that initializes the array with a given size
public SimpleArrayWrapper(int size) {
elements = new int[size];
}
// Method to set an element at a specific index
public void setElement(int index, int value) {
elements[index] = value; // No bounds checking here
}
// Method to get an element at a specific index
public int getElement(int index) {
return elements[index]; // No bounds checking here
}
// Method to get the size of the array
public int getSize() {
return elements.length;
}
}
Fix: Implement bounds checking before accessing elements.
public int getElement(int index) {
if (index < 0 || index >= this.size()) {
throw new IndexOutOfBoundsException("Invalid index: " + index);
}
return this.elements[index];
}
Best Practices
- Always check the length of arrays, lists, strings, or any other data structures before accessing them by index.
- Use loops or conditional statements to ensure indices are within bounds.
- Consider using try-catch blocks to handle potential exceptions and provide a fallback or error message.
Track, Analyze and Manage Errors With Rollbar
Managing errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Java errors easier than ever. Sign Up Today!