JavaマスターJavaプログラムサンプル集例外のサンプル → NullPointerException 対策(その3)

NullPointerException 対策(その3)

実際の開発においてプログラミングを行う場合に、例外の発生によって プログラムが異常終了してしまうという事態は、基本的にはあってはならないことです。 このサンプルでは、NullPointerException が発生しないようにするためには、具体的に どのようなコーディングを行えばよいか、または、発生後にどのような処置を取ればよいのかについて、 基本のパターンを解説します。

NullPointerExceptionに限らず一般的な話ですが、 例外によって停止することがないように する方法は、以下の3通りに区分されます。

  • A. 例外が起こるデータをチェックする
  • B. 例外をキャッチする
  • C. 例外が起こりえない設計を行う

A : 例外が起こるデータをチェックする

もっとも単純な方法として、Personクラスを利用するメソッドにおいて、 そのオブジェクトのフィールドがどのような状態になっているかを、 常に確認してから使うという対策が考えられます。

samples/exception/nullpointer/Person.java - Eclipse SDK
package samples.exception.nullpointer;

public class Person {
  String name;
}

samples/exception/nullpointer/NullPointer3.java - Eclipse SDK
package samples.exception.nullpointer;

public class NullPointer3 {
  public static void main(String[] args) {
    try {
      Person p = new Person();
      // 氏名がnullかどうかを確認します。
      if (p.name == null) {
        System.out.println("氏名がセットされていません");
      else {
        // p.nameがnullではないので、
        // length メソッドを呼び出しても例外は発生しません。 
        System.out.println(p.name.length());
      }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

上記のmainメソッド では、 前回の例と異なり、p.name を使う前に、その値がnullかどうかの確認を行っています。 null の場合は、printNameLengthメソッドを呼び出す代わりに、 警告メッセージを表示するようにしています。

コマンド プロンプト

C:\JavaMaster\bin>java -cp . samples.exception.nullpointer.NullPointer3 
氏名がセットされていません

実際の開発においては、たとえば、このようなメッセージをダイアログボックスで ユーザに表示することができます。その後は、ユーザにデータを修正してもらってから 処理を再実行したり、あるいは、この処理をキャンセルしたりすることができます。

B : 例外をキャッチする

下記のソースコードを、NullPointer3.java と比較してみてください。

samples/exception/nullpointer/NullPointer4.java - Eclipse SDK
package samples.exception.nullpointer;

public class NullPointer4 {
  public static void main(String[] args) {
    try {
      Person p = new Person();
      // 次の処理で、例外が発生する可能性があります。
      System.out.println(p.name.length());
    catch (Exception e) {
      // 例外が発生した場合に、適切な対応をとります。
      // ここでは、ユーザ向けのわかりやすいメッセージを出力することとします。
      System.out.println("氏名の長さを表示する処理において、例外が発生しました。");
    }
    System.out.println("名前の処理が終了しました。");
  }
}

p.nameの値がnullかどうかをif文にてチェックしていないので、 lengthメソッドの実行中にNullPointerExceptionが発生します。 しかし、catchブロックの内部で、適切な処置(ここでは、 ユーザ向けのわかりやすいメッセージを表示する)を実行しています。

コマンド プロンプト

C:\JavaMaster\bin>java -cp . samples.exception.nullpointer/NullPointer4 
氏名の長さを表示する処理において、例外が発生しました。
名前の処理が終了しました。

また、最後に「名前の処理が終了しました。」というメッセージが表示されていることから、 例外をキャッチたあと、その後の処理が問題なく行われる (つまり、例外でプログラムが停止していない) ということがわかります。

NullPointer3.javaが、例外が起きる前に、データを事前にチェックしてメッセージを出力しているのに対し、 NullPointer4.javaでは、例外が起こった後に、メッセージを出力しています。 いずれの方法にしろ、例外でプログラムがストップすることを防いでいるわけです。