java.lang.ArrayIndexOutOfBoundsException: Index X out of bounds for length Y の修正方法

beginner Java2026-04-04| Java Runtime Environment (JRE) / Java Development Kit (JDK) - 全バージョン

Error Message

java.lang.ArrayIndexOutOfBoundsException: Index X out of bounds for length Y
#java#配列#インデックス#例外#ArrayIndexOutOfBoundsException

TL;DR: クイックフィックス

java.lang.ArrayIndexOutOfBoundsException は、存在しないインデックスを使用して配列要素にアクセスしようとしたときに発生します。Javaでは、配列は0から始まるインデックス(ゼロベース)を使用するため、有効な範囲は 0 から length - 1 までです。

これをすぐに修正するには、インデックスが次の条件を満たしていることを確認してください:

if (index >= 0 && index < array.length) {
    // 安全にアクセス可能
    System.out.println(array[index]);
}

通常、これはループの終了条件が i <= array.length になっている場合に発生します。これを i < array.length に変更してください。

根本原因を理解する

Javaの配列は固定サイズの構造です。JVMが配列の割り当てられたメモリ範囲外のインデックスを要求するコードを実行すると、メモリの破損や予期しない動作を防ぐために、この実行時例外をスローします。

エラーメッセージには通常、何が問題だったのかが正確に示されます:

java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5

この例では、配列には5つのスロット(インデックス 0, 1, 2, 3, 4)があります。利用可能な最大のインデックスは常に length - 1 であるため、インデックス 5 を要求するのは不正です。

よくあるシナリオ

- **オフバイワン・エラー(Off-by-One Loop):** forループのヘッダーで `<` の代わりに `<=` を使用している。
- **空の配列:** 長さが 0 の配列に対して `array[0]` にアクセスしようとしている。
- **ハードコードされたインデックス:** 事前に確認せずに、配列が常に特定のサイズであることを前提としている。
- **負のインデックス:** インデックスの計算結果が誤って負の数になっている(例: `i` が 0 のときの `i - 1`)。

ステップバイステップの修正方法

1. ループ境界の修正

これが最も頻繁な原因です。経験の浅い開発者は、配列の長さと最終インデックスを混同しがちです。

問題のあるコード:

int[] numbers = {10, 20, 30};
for (int i = 0; i <= numbers.length; i++) {
    System.out.println(numbers[i]); // i が 3 に達したときに例外をスロー
}

修正後のコード:

for (int i = 0; i < numbers.length; i++) {
    System.out.println(numbers[i]); // 正解: 0, 1, 2 をループする
}

2. 拡張forループ(For-Each)の使用

ロジックに実際のインデックス番号が必要なく、中のデータだけが必要な場合は、拡張forループを使用してください。この構文では反復処理のロジックがJVMによって処理されるため、物理的に ArrayIndexOutOfBoundsException が発生することはありません。

String[] names = {"Alice", "Bob", "Charlie"};
for (String name : names) {
    System.out.println(name);
}

3. 防御的な境界チェック

動的な入力やデータベース/APIからのデータを扱う場合は、使用前に必ずインデックスを検証してください。これは、CLI引数やユーザーが送信したインデックスの場合に特に重要です。

public void processElement(String[] data, int targetIndex) {
    if (data == null || data.length == 0) {
        System.err.println("配列が空または null です");
        return;
    }

    if (targetIndex < 0 || targetIndex >= data.length) {
        System.err.println("無効なインデックス: " + targetIndex);
        return;
    }

    System.out.println("データ: " + data[targetIndex]);
}

4. インデックス計算のデバッグ

インデックスが計算の結果(array[i + j - 1] など)である場合は、クラッシュする直前で計算値をプリントし、実際にどのような数値が生成されているかを確認してください。

int calculatedIndex = i + j - 1;
System.out.println("デバッグ: 長さ " + array.length + " に対してインデックス " + calculatedIndex + " にアクセス中");
System.out.println(array[calculatedIndex]);

修正の検証

修正が機能することを確認するには、配列の境界条件をテストする必要があります:

- **空の配列でテスト:** `length == 0` の場合にクラッシュせず適切に処理されますか?
- **要素が1つの配列でテスト:** インデックス 0 を読み取って停止することを確認します。
- **自動化されたユニットテスト:** JUnitを使用して、範囲外のインデックスが渡されたときに、メソッドが期待通りの値を返すか、適切にエラーを処理することを確認します。
@Test(expected = ArrayIndexOutOfBoundsException.class)
public void testInvalidAccess() {
    int[] arr = {1, 2};
    int fail = arr[2]; // これは失敗するはずであり、エラー処理ロジックのテストが可能です
}

参考資料

- [Oracle公式ドキュメント: ArrayIndexOutOfBoundsException](https://docs.oracle.com/javase/8/docs/api/java/lang/ArrayIndexOutOfBoundsException.html)
- [Javaチュートリアル: 配列](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html)
- [Baeldung: ArrayIndexOutOfBoundsException ガイド](https://www.baeldung.com/java-array-index-out-of-bounds)

Related Error Notes