바쁜 분은 이것만
- 길이가 5인 배열의 인덱스는 0~4. 메시지의
Index 5 ... length 5는 "없는 5번 칸을 읽었다"는 뜻 - 가장 흔한 원인은
i <= arr.length→i < arr.length로 고치기 - 인덱스가 필요 없으면 향상된 for문
for (int x : arr), 내용 확인은Arrays.toString(arr)
java.lang.ArrayIndexOutOfBoundsException은 배열에 없는 칸 번호로 접근했을 때 나는 예외입니다. 메시지에 접근한 번호(Index)와 배열 길이(length)가 같이 나와서 두 숫자만 보면 원인이 대부분 보여요. OpenJDK 27에서 원인별로 직접 재현해 정리했습니다.
1. for문 조건 i <= length (하나 차이 실수)
public class A1 {
public static void main(String[] args) {
int[] scores = {90, 80, 70, 60, 50};
for (int i = 0; i <= scores.length; i++) {
System.out.println(i + ": " + scores[i]);
}
}
}
0: 90
1: 80
2: 70
3: 60
4: 50
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
at A1.main(A1.java:5)
i가 5가 되는 순간 예외가 납니다. 배열 번호는 0부터 시작하니 마지막 칸은 length - 1이에요. 조건을 i < scores.length로 바꾸면 해결됩니다. A1.java:5는 예외가 난 줄 번호예요.
2. 빈 배열에서 [0]
public class A2 {
public static void main(String[] args) {
int[] empty = new int[0];
System.out.println("length = " + empty.length);
System.out.println(empty[0]);
}
}
length = 0
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
at A2.main(A2.java:5)
length 0이 보이면 배열이 비어 있다는 뜻입니다. 첫 번째 값을 꺼내기 전에 if (arr.length > 0)으로 확인해야 해요.
3. 음수 인덱스
public class A3 {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
int last = arr.length - 1;
System.out.println("마지막 값: " + arr[last]);
System.out.println(arr[-1]);
}
}
마지막 값: 3
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 3
at A3.main(A3.java:6)
파이썬처럼 [-1]로 마지막 값을 꺼낼 수 없습니다. 자바에서 마지막 값은 arr[arr.length - 1]이에요. indexOf()가 돌려준 -1(못 찾음)을 그대로 인덱스로 쓸 때도 생겨요.
4. 실행 인자 없이 args[0]
public class A4 {
public static void main(String[] args) {
System.out.println("인자 개수: " + args.length);
String name = args[0];
System.out.println("안녕, " + name);
}
}
인자 없이 java A4.java로만 실행하면:
인자 개수: 0
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
at A4.main(A4.java:4)
args는 실행할 때 파일 이름 뒤에 적은 값들입니다. 아무것도 안 적으면 길이 0인 배열이 들어와요(null이 아닙니다). 개수를 먼저 확인하세요.
public class A5 {
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("사용법: java A5.java 이름");
return;
}
System.out.println("안녕, " + args[0]);
}
}
사용법: java A5.java 이름
5. split 결과를 확인 없이 [1]
public class A6 {
public static void main(String[] args) {
String line = "홍길동";
String[] parts = line.split(",");
System.out.println("parts.length = " + parts.length);
System.out.println(parts[1]);
}
}
parts.length = 1
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1
at A6.main(A6.java:6)
구분자(쉼표)가 없으면 split()은 원래 문자열 하나만 든 배열을 돌려줍니다. 길이를 확인하고 꺼내면 돼요.
public class A11 {
public static void main(String[] args) {
String line = "홍길동";
String[] parts = line.split(",");
String phone = parts.length > 1 ? parts[1] : "(없음)";
System.out.println("이름: " + parts[0] + ", 전화: " + phone);
}
}
이름: 홍길동, 전화: (없음)
6. 2차원 배열: 행 길이와 열 길이 혼동
public class A7 {
public static void main(String[] args) {
int[][] grid = new int[2][3]; // 2행 3열
System.out.println("행 수 grid.length = " + grid.length);
System.out.println("열 수 grid[0].length = " + grid[0].length);
for (int i = 0; i < grid[0].length; i++) { // 행 반복에 열 길이를 씀
for (int j = 0; j < grid.length; j++) {
grid[i][j] = i + j;
}
}
}
}
행 수 grid.length = 2
열 수 grid[0].length = 3
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 2 out of bounds for length 2
at A7.main(A7.java:8)
grid.length는 행 수, grid[i].length는 그 행의 열 수입니다. 바깥 반복에 열 수(3)를 써서 i가 2가 되자 길이 2짜리 행 배열을 넘어섰어요. 안쪽 반복을 grid[i].length로 쓰면 행마다 길이가 다른 배열에서도 안전합니다.
import java.util.Arrays;
public class A8 {
public static void main(String[] args) {
int[][] grid = new int[2][3];
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
grid[i][j] = i + j;
}
}
System.out.println(Arrays.deepToString(grid));
}
}
[[0, 1, 2], [1, 2, 3]]
7. List는 메시지가 조금 다르다
import java.util.ArrayList;
import java.util.List;
public class A9 {
public static void main(String[] args) {
List<String> list = new ArrayList<>(List.of("a", "b", "c"));
System.out.println("size = " + list.size());
System.out.println(list.get(3));
}
}
size = 3
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:100)
...
at java.base/java.util.ArrayList.get(ArrayList.java:428)
at A9.main(A9.java:8)
ArrayList의 get()은 앞에 Array가 빠진 IndexOutOfBoundsException을 던지고, 내 코드 위치는 트레이스 맨 아래 줄에 있어요. ArrayIndexOutOfBoundsException은 IndexOutOfBoundsException의 하위 클래스라 원인과 고치는 방법은 같습니다. 배열은 length, List는 size()로 길이를 확인합니다.
8. 예방: 향상된 for문과 Arrays.toString
import java.util.Arrays;
public class A10 {
public static void main(String[] args) {
int[] scores = {90, 80, 70, 60, 50};
System.out.println("println(배열): " + scores);
System.out.println("Arrays.toString: " + Arrays.toString(scores));
int sum = 0;
for (int s : scores) {
sum += s;
}
System.out.println("합계: " + sum);
for (int i = 0; i < scores.length; i++) {
System.out.println(i + ": " + scores[i]);
}
}
}
println(배열): [I@58134517
Arrays.toString: [90, 80, 70, 60, 50]
합계: 350
0: 90
1: 80
2: 70
3: 60
4: 50
배열을 그냥 출력하면 [I@58134517(타입과 해시코드, 실행마다 다름)만 나옵니다. Arrays.toString()으로 찍으면 값이 보이고, 2차원 배열은 Arrays.deepToString()을 써요. 인덱스가 필요 없는 반복은 향상된 for문 for (int s : scores)로 쓰면 범위를 틀릴 일 자체가 없어요.
정리
| 메시지 / 상황 | 원인과 해결 |
|---|---|
| Index 5 ... length 5 | i <= length → i < length |
| Index 0 ... length 0 | 빈 배열 또는 인자 없는 args[0] → length 먼저 확인 |
| Index -1 | 음수 인덱스 불가 → 마지막은 arr[arr.length - 1] |
| split 후 Index 1 ... length 1 | 구분자 없음 → parts.length > 1 확인 |
| 2차원 배열 | 행 grid.length, 열 grid[i].length |
참고: Oracle Java SE API 문서 — ArrayIndexOutOfBoundsException, IndexOutOfBoundsException, List.get, String.split, Arrays.toString / deepToString, Object.toString / The Java Tutorials — Arrays, The for Statement(enhanced for), Command-Line Arguments / JLS 10.4 Array Access
