Code Fix

中級

ArrayIndexOutOfBoundsException の原因と直し方

添字が0始まりであることの帰結です。ループ条件の < と <= の使い分けを整理します。

エラーメッセージの読み方

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:
main
スレッド名 — mainなら起動直後の処理で発生しています
java.lang
パッケージ — java.lang なら標準の基本例外です
ArrayIndexOutOfBoundsException
例外クラス — 何が起きたか。ここを検索するのが最短です

このエラーが出る典型パターン

パターン1

 1  public class Main {
 2      public static void main(String[] args) {
 3          int[] nums = {10, 20, 30};
 4          for (int i = 0; i <= nums.length; i++) {
                               ^
 5              System.out.println(nums[i]);
 6          }
 7      }
 8  }
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3exited with code 1

長さ3の配列の添字は0,1,2です。全要素を回るループは < が正解です。

直し方: <= を < にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  public class Main {
 2      public static void main(String[] args) {
 3          int[] nums = {10, 20, 30};
 4          System.out.println(nums[nums.length    ]);
                                           ^
 5      }
 6  }
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3exited with code 1

最後の要素の添字は length - 1 です。添字が0始まりであることの直接的な帰結です。

直し方: nums.length を nums.length - 1 にします。

この問題を解いてみる →

パターン3

 1  public class Main {
 2      public static void main(String[] args) {
 3          int[] nums = new int[3];
 4          for (int i = -1         ; i < nums.length; i++) {
                              ^
 5              nums[i] = i;
 6          }
 7          System.out.println(nums[0]);
 8      }
 9  }
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 3exited with code 1

負の添字も範囲外です。Javaでは末尾から数える書き方はできません。

直し方: -1 を 0 にします。

この問題を解いてみる →

パターン4

 1  public class Main {
 2      public static void main(String[] args) {
 3          int[] nums = {10, 20, 30};
 4          for (int i = nums.length    ; i >= 0; i--) {
                                ^
 5              System.out.println(nums[i]);
 6          }
 7      }
 8  }
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3exited with code 1

逆順ループの開始位置も length - 1 です。最後の要素の添字は length ではありません。

直し方: nums.length を nums.length - 1 にします。

この問題を解いてみる →

パターン5

 1  public class Main {
 2      public static void main(String[] args) {
 3          int[] nums = new int[0          ];
                                      ^
 4          System.out.println(nums[0]);
 5      }
 6  }
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0exited with code 1

サイズ0の配列には要素が1つもありません。使う前に配列の大きさを確認する習慣が大切です。

直し方: 0 を 1 にします。

この問題を解いてみる →

よくある誤解

例外メッセージの Index N が、実際に触った添字です。ループ条件を睨む前にこの数字を読むと原因が早く分かります。

実務での勘所

配列の範囲外アクセスは、C言語のように未定義動作としてメモリを壊すのではなく、JVMが毎回の添字アクセスで境界を検査し、範囲外なら必ず例外を投げるという設計です。この検査には多少の実行コストがありますが、安全性を優先した設計判断です。添字そのものを使わずに要素を順に処理するだけなら、for (int i = 0; i < arr.length; i++)の代わりにfor (int x : arr)という拡張for文を使えば、そもそも添字を書かないためこの種のミスが原理的に起きません。

演習をはじめる

関連するエラー

他の言語ではどうなるか

広告
広告スロット(未設定)