プログラミング初心者にとってなかなか苦労するのが、エラーが出たときのバグ取りだろう。
Javaだとコンパイラでチェックをしてくれるが、そこで出てくるエラーも対処がわからないことが多いはずだ。
このページでは初心者の方がよく出会うJavaのエラーについてまとめてみた。参考にしていただければと思う。
目次
Javaのエラー表示について
Javaプログラミングでよくあるエラーを紹介する前に、どのような書式でエラーが表示されるかを見ておこう。
まだ中身がわからない方も多いと思うので、参考程度に見ていただくだけでも十分だ。後で役に立つ。
たとえば、このようなプログラムを作ったとしよう。
1 2 3 4 5 6 7 8 9 10 |
package sample; public class SampleClass { public static void main(String[] args) { setArray(); } public static void setArray(){ int list[] = new int[10]; list[20] = 1; } } |
"main"メソッドから"setArray"メソッドを呼び出して、配列"list"に値を設定するものだ。
このプログラムを実行すると、後でも紹介するエラーのひとつ"ArrayIndexOutOfBoundsException"が発生する。
1 2 3 |
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 20 at sample.SampleClass.setArray(SampleClass.java:8) at sample.SampleClass.main(SampleClass.java:4) |
それでは、このエラー表示を読み解いてみよう。
- 1行目にはどのようなエラーが発生したかが表示される。この場合は"ArrayIndexOutOfBoundsException"だ。
- 2行目の"at"以降には、どこでエラーが発生したのかが表示される。この場合はjavaの8行目だ。
- 3行目以降も"at"が続き、どこでエラーが発生したのかが表示される。2行目は実際にエラーが発生した場所だが、3行目以降はエラーが発生したメソッドを呼び出した場所が表示される。
このプログラムでは"main"メソッドから"setArray()"メソッドを呼び出しているので2階層になっているが、実際のプログラムではもっと複雑な構成になることが多い。その場合、3行目以降に何行も呼び出しクラスが表示されることになる。
エラーの解析を行うには、この情報をもとに、どのような経緯でエラーが発生したクラスやメソッドが呼び出され、どのクラスやメソッドに問題があるかを解析する必要がある。
なお、このようなエラー情報はスタックトレースと呼ばれ、Javaが実行時に使用する"スタック"というメモリー領域に記録される情報を表示している。
スタックトレースはデバッグには欠かせない、何かと役にたつ重要な情報なので覚えておこう。
Javaのエラーとその対策
それでは、代表的なエラーとその対策を紹介しよう。
java.lang.NullPointerException
エラー内容
このエラーはnullのオブジェクトに対してアクセスしようとしたときに発生する。プログラミング時に比較的発生しやすいエラーで、エンジニアの間では「ヌルポ」と呼ばれている。
サンプルプログラム
1 2 3 4 5 6 7 |
package sample; public class SampleClass { public static void main(String[] args) { String buf = null; System.out.println("buf length is " + buf.length()); } } |
実行結果
1 2 |
Exception in thread "main" java.lang.NullPointerException at sample.SampleClass.main(SampleClass.java:5) |
対策
- インスタンスの生成や値の設定が正しく行われているかをチェックする。
- オブジェクトがnullになってしまうタイミングをデバッグで確認する。
- プログラムでオブジェクトがnullかどうかのチェックを行い、エラーの発生をできる限り回避する。
java.lang.ArrayIndexOutOfBoundsException
エラー内容
配列のインデックスとして存在しない要素を指定した場合に発生するエラーで、先ほどのエラーの例でも紹介した。配列のインデックスとして1~10のインデックスしかないところ、20のインデックスに値を設定しようとする場合などに発生する。
サンプルプログラムと実行結果は最初に紹介した例を参照してほしい。
対策
- 正しい配列のインデックスを指定できているかチェックする。
- 配列の設定を繰り返し処理で行っている場合、繰り返し回数などに問題がないかチェックする。
java.lang.NumberFormatException
エラー内容
このエラーは文字列の値を数値に変換(キャスト)しようとしたが、文字列に数値として正しくない値が設定されている場合に発生する。
サンプルプログラム
1 2 3 4 5 6 7 |
package sample; public class SampleClass { public static void main(String[] args) { int intVal; intVal = Integer.valueOf("文字列をキャスト").intValue(); } } |
実行結果
1 2 3 4 5 |
Exception in thread "main" java.lang.NumberFormatException: For input string: "文字列をキャスト" at java.lang.NumberFormatException.forInputString(Unknown Source) at java.lang.Integer.parseInt(Unknown Source) at java.lang.Integer.valueOf(Unknown Source) at sample.SampleClass.main(SampleClass.java:5) |
対策
- 文字列にアルファベットや記号など、数値以外の文字が設定されていないかチェックする。
- 文字列に空白やnullが設定されていないかチェックする。
- 文字列には数値が設定されているが、変換しようとしている数値型で扱える値の範囲をオーバーしていないかチェックする。
java.lang.ClassCastException
エラー内容
このエラーはあるクラスを変換できないクラスにキャストしようとした時に発生する。
サンプルプログラム
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package sample; import java.util.Date; import java.util.HashMap; public class SampleClass { public static void main(String[] args) { HashMap map = new HashMap(); Date dt = new Date(); map.put("birthday", "2000/01/01"); Date birthday = (Date)map.get("birthday"); System.out.println(birthday); } } |
実行結果
1 2 |
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Date at sample.SampleClass.main(SampleClass.java:10) |
対策
- 配列などに設定した値のクラスと、値を取り出す時にキャストしようとしている型が一致しているかをチェックする。
- 継承関係のある2つのクラスで、サブクラスにスーパークラスをキャストしようとしていないかをチェックする。
java.lang.ArithmeticException
エラー内容
このエラーは数値の計算において、不正な算術処理が行われた場合に発生する。例えば数学的にあり得ない「ゼロ除算(10÷0 など)」が発生するとこのエラーが発生する。
サンプルプログラム
1 2 3 4 5 6 7 8 9 10 11 12 |
package sample; public class SampleClass { public static void main(String[] args) { int valueA; int valueB; int result; valueA = 100; valueB = 0; result = valueA / valueB; } } |
実行結果
1 2 |
Exception in thread "main" java.lang.ArithmeticException: / by zero at sample.SampleClass.main(SampleClass.java:10) |
対策
- ゼロ除算が行われてないかをチェックする。
- 数値型変数で計算している場合、割る数の変数にゼロが設定されていないかチェックする。
java.lang.NoClassDefFoundError
エラー内容
メソッドを呼び出す時や、インスタンスを生成しようとしている時に、Javaがクラス定義を読み込むことができないエラーだ。
対策
- 環境変数CLASSPATHが誤っている可能性があるのでチェックする。
- ファイル名やパッケージ名に誤りがないかチェックする。
- プログラムに必要な外部ファイル(jar)が読み込まれているかチェックする。
java.lang.OutOfMemoryError
エラー内容
Javaは実行時にスタック領域とヒープ領域という2つのメモリー領域を使用するが、このエラーはプログラムの実行に必要なヒープ領域のメモリーサイズが不足した時に発生する。
ヒープ領域とはクラスやメソッドの定義など、オブジェクトのインスタンスが割り当てられるメモリー領域のことだ。
対策
- プログラム内で無限ループになっていしまっている箇所がないかチェックする。
- 一度に大量のデータを処理しようとしている箇所がないかチェックする。
- 不必要にスコープ(公開範囲)が広いメソッドや変数を多用していないかチェックする。
このエラーの場合、環境によってはJVM(Java仮想マシン)のヒープ領域のメモリーサイズをチェックし、必要な場合はチューニングすることが可能だ。ただし、チューニングすることで別のアプリケーションのメモリーが不足するケースなどもあるので、注意が必要だ。
JVMのヒープ領域のチューニングについては、別の機会で紹介することにする。
まとめ
このページでは初心者の方がよく捕まるJavaのエラーについてまとめてきた。
ここの辺りのエラーを対処できれば、概ねプログラミングするときに困ることがなくなるはずだ。ぜひ参考にしていただければと思う。
>Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 20
>at sample.SampleClass.setArray(SampleClass.java:8)
>at sample.SampleClass.main(SampleClass.java:4)
>2行目の"at"以降には、どこでエラーが発生したのかが表示される。この場合はjavaの13行目だ。
まったく意味が解りませんでした。
2行目には「SampleClass.java:8」とあり、8行目なのかと思いきや説明では13行目。
しかも例とした構文は10行目で閉じていますし、どういう意味なのでしょうか。
listは配列は1~10までなのに、20に1を入れようとしたからエラーになっていて、
その1を入れているところが8行目なので、
>at sample.SampleClass.setArray(SampleClass.java:8)
なのかな。
で、エラーが発生したメソッド「setArray」が4行目なので、
>at sample.SampleClass.main(SampleClass.java:4)
なのかな。
「13行目」は解説文のコピーミスか何かですかね。失礼いたしました。
いつもご愛読いただきありがとうございます。
ご指摘頂きました通り、エラー文の解説について「13行目」ではなく「8行目」が正しい記述となります。該当の箇所につきましては修正させて頂きました。
今後とも、ご愛読のほどよろしくお願いいたします。