これさえ見ればもう怖くない! Javaでよく出るエラーと対策5選
目次
こんにちは、堀部です。
Javaで開発を行っていると決まって登場してくるあいつら……。よく登場してくるのでその都度対処法を調べていると時間もかかる、ということで良く出くわす奴らを対策と共にまとめてみました。
これさえ読めばあなたはもうJava初心者とは呼ばれないはず?
ラインナップは以下の通り。
目次
- NullPointerException
- ArrayIndexOutOfBoundsException
- NumberFormatException
- ClassCastException
- OutOfMemoryError
NullPointerException
登場回数No.1のいわゆる「ぬるぽ」というやつです。この例外はnull値(定義されていない値のこと)の参照型変数を参照しようとした時に発生します。
コード例
public class NullPointerExceptionSample { public static void main(String[] args) { String str = null; System.out.println(str.toString()); } }
出力結果
Exception in thread "main" java.lang.NullPointerException at NullPointerExceptionSample.main(NullPointerExceptionSample.java:4)
出力結果を見るとわかる通り、コード例の4行目で例外が発生しています。null値のstr変数に対してtoString()しようとしてるためです。Stringの変数に対してtoString()することはありませんが、単純な例として記載しています。
基本的には”参照型変数.メソッド名”のコードで参照型変数がnullの場合に出ることが多いですが、メソッドの引数にnullを渡してもたまに出ることがあります。
コード例
import java.math.BigDecimal; public class NullPointerExceptionSample { public static void main(String[] args) { BigDecimal one = new BigDecimal("1.00"); BigDecimal add = one.add(null); } }
出力結果
Exception in thread "main" java.lang.NullPointerException at java.math.BigDecimal.add(BigDecimal.java:1083) at NullPointerExceptionSample.main(NullPointerExceptionSample.java:6)
<対策>
null値の考慮をしましょう。参照型変数に対してnullかどうかの判定を行うだけで、例外の発生を回避することができます。
コード例
public class NullPointerExceptionSample { public static void main(String[] args) { String str = null; if ( str != null) { System.out.println(str.toString()); } else { System.out.println("null値です。"); } } }
出力結果
null値です。
ArrayIndexOutOfBoundsException
配列などで不正なインデックスを参照するとこの例外が発生します。
コード例
public class ArrayIndexOutOfBoundsException { public static void main(String[] args) { String[] str = new String[3]; str[0] = "one"; str[1] = "two"; str[2] = "three"; for ( int i = 0; i <= str.length; i++) { System.out.println(i + "件目は" + str[i]); } } }
出力結果
0件目はone 1件目はtwo 2件目はthree Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 at ArrayIndexOutOfBoundsException.main(ArrayIndexOutOfBoundsException.java:8)
このコードでは8行目で例外が発生していますが、まずいのは7行目です。for文の条件が「i <= str.length」と「=」がついていることが原因です。このように例外によっては発生した場所と原因となる場所が異なることがあるので注意が必要です。
<対策>
Javaの配列は1件目のインデックスは「0」となります。3件分の配列を定義した場合、インデックスとしては0件目から2件目までの3件分が存在しますので、そのことを忘れずにコーディングしましょう。
コード例
public class ArrayIndexOutOfBoundsException { public static void main(String[] args) { String[] str = new String[3]; str[0] = "one"; str[1] = "two"; str[2] = "three"; for ( int i = 0; i < str.length; i++) { System.out.println(i + "件目は" + str[i]); } } }
出力結果
0件目はone 1件目はtwo 2件目はthree
NumberFormatException
文字列を数値型に変換した際に、数値以外の文字が含まれるなどして変換ができない場合に発生します。
コード例
public class NumberFormatExceptionSample { public static void main(String[] args) { String str = "abc"; int n1 = Integer.parseInt(str); System.out.println(str + " を変換すると " + n1); } }
出力結果
Exception in thread "main" java.lang.NumberFormatException: For input string: "abc" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:492) at java.lang.Integer.parseInt(Integer.java:527) at NumberFormatExceptionSample.main(NumberFormatExceptionSample.java:4)
String型の変数をparseIntメソッドによってint型に変換していますが、String型の変数が数値ではないため例外が発生しています。
int型は整数値を扱うデータ型ですので小数点を含む値(例えば1.1)や、最大値以上の値(int型の場合は2147483647まで)を変換しようとしても例外が発生します。
<対策>
try-catch文で例外処理を行いましょう。正規表現やライブラリを使って数値型への変換前にチェックを行う方法もありますが、まずはこの方法をマスターしましょう。
NumberFormatExceptionは数値チェックのためにあえて発生させる場合もありますが、例外の発生はコストがかかりますのであまりにも発生頻度が多い場合は、事前チェックも検討する必要があります。
コード例
public class NumberFormatExceptionSample { public static void main(String[] args) { String str = "abc"; try { int n1 = Integer.parseInt(str); System.out.println(str + " を変換すると " + n1); } catch (NumberFormatException e) { System.out.println(str + " は数値ではありません。 "); } } }
出力結果
abc は数値ではありません。
ClassCastException
クラスのキャスト(型変換)に失敗すると発生する例外です。
コード例
public class ClassCastExceptionSample { public static void main(String[] args) { Object obj = "123"; System.out.println((Integer)obj); } }
出力結果
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer at ClassCastExceptionSample.main(ClassCastExceptionSample.java:4)
Object型の変数に「123」という値を代入していますが、String型の値に対して4行目でInteger型にキャストしているため発生しています。
<対策>
NumberFormatExceptionの時のようにtry-catch文を使用することもできますが、この例外の場合は「instanceof」で型をチェックすることができます。
コード例
public class ClassCastExceptionSample { public static void main(String[] args) { Object obj = "123"; if ( obj instanceof Integer ) { System.out.println((Integer)obj); } else { System.out.println("Integer型ではありません。"); } } }
出力結果
Integer型ではありません。
OutOfMemoryError
Javaのメモリにはヒープ領域というものがありますが、処理の高負荷などによってメモリ不足になるとこのエラーが発生します。前述の4つと違いこれはExceptionではなくErrorです。
ExceptionとErrorの違いは簡単に言ってしまうと、発生する場所が違います。Exceptionはプログラム内で発生しますが、ErrorはJava仮想マシン(JVM)で発生します。
コード例
public class OutOfMemoryErrorSample { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); while (true) { sb.append("123"); } } }
出力結果
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:2367) at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:130) at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:114) at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:415) at java.lang.StringBuilder.append(StringBuilder.java:132) at OutOfMemoryErrorSample.main(OutOfMemoryErrorSample.java:5)
<対策>
JavaにはGC(ガベージコレクション)という仕組みによって不要となったオブジェクトを自動的に開放する仕組みがありますが、それでも実装の仕方によってはこのエラーが発生することがあります。
またプログラムは特に問題なく動いているが、ある日突然メモリ不足でこのエラーが発生することもあり原因となる部分が見つけにくいのも特徴です。大量データを扱うときには特に注意しましょう。
まとめ
いかがでしたでしょうか?
Javaにはまだまだ多くの例外がありますが、基本的なものを押さえておけば対処も素早くできると思います。例外の特徴をしっかりと抑えてより良いコードが書けるように心掛けていきましょう。
《関連記事》