NullPointerExceptionとは?
メソッドや配列にnull値を渡し、参照しようとした場合などに発生しやすい例外・エラーになっています。
NullPointerExceptionの詳しい説明は、以下の記事にまとめていますので参考までに。
【関連記事】
▶︎【Java】NullPointerExceptionの原因と回避方法を解説
NullPointerExceptionの対策方法
NullPointerExceptionを発生させないためには、どのようにすればよいのでしょうか?
NullPointerExceptionは、JavaやC言語、C++といったさまざまな言語で発生し得る例外です。ここでは、どんな言語にでも対応できる対策方法の一例を紹介します。
NullPointerExceptionを発生させないためには、「null」を使用しなければよいです。
当たり前のように感じるかも知れませんが、変数や配列の初期化でnullを使用している人もいるでしょう。
初期化する際は、以下のサンプルコードのようにnull以外で初期化します。
public class NullPointerExceptionSample { public static void main(String[] args) { // nullで初期化してそのまま実行すると NullPointerException が発生します String str1 = null; // 下記のように、null以外で初期化しましょう String str2 = "ポテパン"; StringLength(str2); } static void StringLength(String str) { int strlen = str.length(); System.out.println(str + "は" + strlen + "文字です"); } }
また、仮にnullが入っていても例外を検出できるように、if文を使ってnullかどうかを判定する方法があります。
下記のサンプルコードで見ていきましょう。
public class NullPointerExceptionSample { public static void main(String[] args) { String str1 = null; try { if(str1 != null) { int strlen = str1.length(); System.out.println(str1 + "は" + strlen + "文字です"); } else { throw new NullPointerException(); } } catch(NullPointerException e) { e.printStackTrace(); } String str2 = "ポテパン"; try { if(str2 != null) { int strlen = str2.length(); System.out.println(str2 + "は" + strlen + "文字です"); } else { throw new NullPointerException(); } } catch(NullPointerException e) { e.printStackTrace(); } } }
try-catch文の中にif文で、参照型変数(str1、str2)がnullでないかどうかを判定しています。
nullだった場合は、「throw new NullPointerException();」で例外を発生させ、catchで例外を補足しているのです。
上記のサンプルコードを実行すると、以下の実行結果になります。
実行結果↓
java NullPointerExceptionSample java.lang.NullPointerException at NullPointerExceptionSample.main(NullPointerExceptionSample.java:11) ポテパンは4文字です
Javaの4つのエラーの原因と対策方法
Javaの例外には、NullPointerException以外にも代表的なものが4つあります。
- ArrayIndexOutOfBoundsException
- ClassCastException
- NumberFormatException
- OutOfMemoryError
ひとつずつ解説しますね。
①ArrayIndexOutOfBoundsException
ArrayIndexOutOfBoundsExceptionは、配列が不正なインデックスによってアクセスされた場合に発生する例外です。
インデックスの値が負の際や、配列のサイズ以上のインデックスを指定した場合に発生します。
下記のサンプルコードで見ていきましょう。
public class ArrayIndexOutOfBoundsExceptionSample { public static void main(String[] args) { int[] intarr = new int[3]; intarr[0] = 10; intarr[1] = 20; intarr[2] = 30; for(int index = 0; index <= intarr.length; index++){ System.out.println(index + "件目の要素" + intarr[index]); } } }
int型の配列の中身を出力するプログラムです。
一見、正常に動くように見えるかもしれませんが、「index <= intarr.length」のため、存在しないintarr[3]まで出力しようとしています。
正常に動かすには、「index < intarr.length」にすればOKです。
このプログラムを実行すると、以下の実行結果が得られます。
実行結果↓
0件目の要素10 1件目の要素20 2件目の要素30 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 at ArrayIndexOutOfBoundsExceptionSample.main(ArrayIndexOutOfBoundsExceptionSample.java:10)
ArrayIndexOutOfBoundsExceptionの対策方法は、配列のインデックスについてしっかり把握することに限ります。
配列の1件目は「0」からインデックスが始まります。
上記プログラムの例でいうと、配列の要素数を3で定義しました。
インデックスは0〜2までの3つ分になります。
②ClassCastException
ClassCastExceptionは、継承関係にないサブクラスにキャスト(型変換)した場合に発生する例外です。
下記のサンプルコードで見ていきましょう。
public class ClassCastExceptionSample { public static void main(String[] args) { Object obj = "100"; System.out.println((Number)obj); } }
Object型の変数を用意し、出力する際にNumber型の変数にキャストしています。
ObjectとNumberは継承関係にないため、このプログラムを実行すると以下のようにエラーが発生します。
実行結果↓
Exception in thread "main" java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap') at ClassCastExceptionSample.main(ClassCastExceptionSample.java:4)
ClassCastExceptionの対策方法は、try-catch文でエラーを検出するか「instanceof」で型チェックをするとよいでしょう。
instanceofの使い方は、以下の記事で詳しく解説しています。
【関連記事】
▶︎Javaのif文6つの書き方をわかりやすく解説【サンプルコードあり】
③NumberFormatException
NumberFormatExceptiongは、文字列を数値型に変換しようとする際に、文字列の形式が正しくない場合に発生する例外です。
下記のサンプルコードで見ていきましょう。
public class NumberFormatExceptionSample { public static void main(String[] args) { String str = "ポテパン"; int number = Integer.parseInt(str); System.out.println(str + " をintに変換すると " + number); } }
String型の変数strを「parseIntメソッド」でint型に変換しています。
しかし、文字列「ポテパン」は数値ではないために例外が発生するのです。
上記のプログラムを実行すると、以下の実行結果が得られます。
実行結果↓
Exception in thread "main" java.lang.NumberFormatException: For input string: "ポテパン" at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68) at java.base/java.lang.Integer.parseInt(Integer.java:658) at java.base/java.lang.Integer.parseInt(Integer.java:776) at NumberFormatExceptionSample.main(NumberFormatExceptionSample.java:4)
なお、parseIntメソッドについて詳しく知りたい人は、以下の記事を参考にしてみてください。
【関連記事】
▶︎【初心者歓迎】Javaで数値(int)と文字列(String)の変換方法をわかりやすく解説!
NumberFormatExceptiongの対策方法、try-catch文による例外処理や正規表現を使った変換チェックを行うのがよいです。
④OutOfMemoryError
OutOfMemoryErrorは、メモリ不足によってオブジェクトを割り当てられず、使用可能なメモリを確保できない場合に発生するエラーです。
下記のサンプルコードで見ていきましょう。
public class OutOfMemoryErrorSample { public static void main(String[] args) { StringBuffer buf = new StringBuffer(); while (true) { buf.append("ポテパン"); } } }
StringBuffer型の変数bufに、trueの間(無限)「ポテパン」という文字を追加する処理になっています。
上記の文章からわかると思いますが、ずっとポテパンという文字を追加していれば、いつか空きスペースがなくなってエラーが起こりますよね。
上記のプログラムを実行すると、以下の実行結果が得られます。
実行結果↓
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.base/java.util.Arrays.copyOf(Arrays.java:3746) at java.base/java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:172) at java.base/java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:538) at java.base/java.lang.StringBuffer.append(StringBuffer.java:312) at OutOfMemoryErrorSample.main(OutOfMemoryErrorSample.java:5)
プログラムが正常に動いていても、メモリ不足になるとエラーが発生してしまうので、見つけるもは難しいエラーとも言えます。
OutOfMemoryErrorの対策方法は、大量データを扱うときや上記のようにループを回すときの構文ミスなどに気をつけるとよいでしょう。
まとめ
NullPointerExceptionの意味や対策方法、その他Javaで発生しやすい例外・エラーを紹介しました。
例外・エラーの意味や対策方法を覚えておけば、現象が発生してもスムーズに対応可能です。
例外が発生してしまった際は、ぜひこの記事を参考に活用してください!
NullPointerExceptionとは、参照型変数にnull値が格納されている時に、参照型変数を参照しようとした場合に発生する例外です。