반응형

바쁜 분은 이것만

  1. 길이가 5인 배열의 인덱스는 0~4. 메시지의 Index 5 ... length 5는 "없는 5번 칸을 읽었다"는 뜻
  2. 가장 흔한 원인은 i <= arr.length → i < arr.length로 고치기
  3. 인덱스가 필요 없으면 향상된 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

반응형

+ Recent posts