Sassyブログ

好きなことで暮らしを豊かにするブログ

Java入門者向け!例外処理について

1.例外処理とは

プログラムの処理中に何らかしらの異常が発生したときに処理を上位の処理に戻して、
その異常を適切に処理してシステムを正常の状態に戻す処理のこと。
 

2.なぜ例外処理を行うのか

必ずしもシステムは完璧には動きません。
ましてや流れてくるデータがすべて正常なデータであると保証できれば、
まぁ100歩譲って完璧には動いてくれるかもしれません。
しかし、近年のシステムは様々な(外部の)システムと絡み合っています。
その中で常に正常なデータが流れてくることは保証できないし、ネットワークでつながってる以上ネットワークによる異常も発生する可能性もあります。
そして、常に利用者はシステムを理解して利用している人に限定されません。
当然、一般ユーザーはそのシステムのことなんて知らないし、また入力をミスることもあります。
 
そのような中で例外処理を適切に行うことは非常に重要です。
 
実際に運用しているシステムでは、適切な例外処理を行っていないと次のような負債などを被ります。
 
・異常発生時にログの取得が行えないため、異常発生個所の特定が難航し保守コストがかかります。
・ユーザーが不正なデータを入力してしまった場合に急にアプリケーションの処理が終了して、エラーメッセージも表示されずクレームにつながります。
 
そのため、例外処理はシステムを正常に稼働させるために必ず必要になってくるものであることを認知していただきたいと思います。
 

3.検査例外と非検査例外について

おそらくJava始めて間もない人には聞きなれない用語かもしれません。
 

3-1.検査例外とは

検査例外は必ず呼び出し元でcatchして例外処理をしてあげなければいけない例外です。
つまり、呼び出し側が与えたデータがきっかけで例外になってしまったという責任があり、
あなたのせいで例外が発生したんだからあなたが処理してよねという例外です。
 
そして、EclipseなどのIDEを利用していると、あるメソッドを呼び出したときに「catchしてください」というようなエラーだか警告メッセージが表示されるはずです。
 
このメッセージが表示されるのは、呼び出し先のメソッドでExceptionまたはそれを継承している例外クラスがthrowされているからです。
 

3-2.非検査例外

上記の検査例外の流れからしてcatchしなくてもよい例外です。
しかし、catchしなくてもよい例外とは語弊がありますね。
正しくはcatchする必要のない例外が適切かもしれないです。
 
そのため、この例外が発生した時点で呼び出し元の最上位まで上がっていきアプリケーションは処理を停止します。
これは呼び出し元に責任はなく、プログラマの実装ミスやシステム的に異常がある場合に発生させる例外です。
システム的な異常とは具体的にシーンで言いますと、システムが稼働するために必要な設定ファイルやマスタデータ、DB異常、外部システム異常が発生したなどです。
これらの異常がある以上、システムはまともに稼働できないため強制的にアプリケーションを停止させる必要があります。
 
 

4.例外処理の実践的なやり方

おそらく現場経験のない方は例外処理を行う際に参考書などの例外処理の説明以外のところに記載してある例外処理などを参考にして実装してしまうかもしれません。
よほど丁寧な参考書であれば別ですが、これはかなり危険です。
 
なぜなら、上記の箇所で載せているソースコード内にある例外処理はあくまでそこに視点を置いておらず仮で記載されているケースがほとんどであるからです。
 
多分、多くはExceptionでcatchしているかと思います。
 
しかし現場レベルになると何でもかんでもExceptionでcatchしていたら怒られます。
 
というのもExceptionは範囲が広いので色々な例外がキャッチされてしまいます。
例外キャッチは発生しうる例外にとどめておくべきです。
そして、その個々の例外に対して適切な例外処理を記述すべきです。
 

5.ExceptionとRuntimeExceptionの実践的な使い方

例外をスローする際についてお話します。
 
まず現場レベルでアプリケーションなどを開発していますとほぼほぼExceptionとRuntimeExceptionで例外をスローすることはないです。
 
それらを継承した例外クラスを作成します。
 
その継承した例外クラスを異常ケースに合わせてスローします。
 
 
作成する例外クラスイメージとしては以下のような感じになります。
※今回は検査例外用と非検査例外用に分けて作成してみます。
 
【検査例外用例外クラス】
public class CheckedException extends Exception {
 
     private String errCode;
     private String errMsg;
     private Throwable cause;
 
     public CheckedException(String errCode, String errMsg) {
           this.errCode = errCode;
            this.errMsg = errMsg;
     }
 
     public CheckedException(String errCode, String errMsg, Throwable cause) {
          this.errCode = errCode;
          this.errMsg = errMsg;
          this.cause = cause;
     }
 
・・・・省略
 
}
 
 
【非検査例外用例外クラス】
public class UncheckedException extends RuntimeException {
 
     private String errCode;
     private String errMsg;
     private Throwable cause;
 
     public CheckedException(String errCode, String errMsg) {
          this.errCode = errCode;
          this.errMsg = errMsg;
     }
 
     public CheckedException(String errCode, String errMsg, Throwable cause) {
          this.errCode = errCode;
          this.errMsg = errMsg;
          this.cause = cause;
     }
 
・・・・省略
 
}
 
こんな感じに分けて作成します。
 
これを自分らのアプリケーション内で利用するのが一般的なであるのかなと感じます。
 
 

6.最後に

これからITの現場に出てプログラミングする方または現場に出て間もない方、そして自身でアプリケーション開発を行う方は適切な例外処理ができるようにこの箇所ではどんな異常が発生しそうか?また、発生した場合どのように例外処理を行うべきかを常に考えながら実装するとよいかと思います。
 
そして初心者の方は、どうしてこの例外をキャッチしているのか?という疑問も出てくるかと思います。それに関してはすべてJavaDocに記載してありますのでJavaDocを確認してみてください。
JavaDocも人が作るものなのでどうしても信用できない方やJavaDocが見当たらない場合は実装を直接見るしかないかと思います。
 
 
以上