So-net無料ブログ作成

【Java】 例外は難しい ①

本ブログの方でもチラっと触れたことがあるけど、
まぁ偉そうな事を言っておいて私自身も実は例外周りはイマイチしっくり書けたことがない。。。
Javaの例外周りの仕様は残念ながらモヤっとしている部分が有るので、
「こう書くとOK」みたいなのが無いのが原因なのかなと。
…という訳でまずは仕様周りから攻めてみたい。

【Throwable】
言わずと知れたException(とError)の親玉。以下のような特徴を持つ。
・実行スタックを積んでくれる。(ありがたやー)
・その名の通りスロー可能になる。もっと言うと
 - メソッドの右肩にthrowsとしてリスト出来るよ
 - インスタンス化してスロー(throw)出来るよ
 - スローされたオブジェクトを呼び元でcatch出来るよ
尚、ErrorとRuntimeExceptionおよびそれらのサブクラス以外はコンパイラにより例外チェック機構が走り、
それらがスローされる可能性(+外に伝播する可能性)がある場合にはthrows宣言しなければならない。
「- メソッドの右肩にthrowsとしてリスト出来るよ」が強制される訳です。
さらに踏み込むとthrows宣言したくない場合は潰す、即ちcatchしなければならない…ということです。

【Exception】
Throwableの子供その1。
キャッチされる可能性のあるThrowableの形式の一つ。ちなみにもう一つの形式が次のError。
Exceptionがスローされてそのメソッドやコンストラクタの外に出る場合はthrows節で宣言しなければならない。

【Error】
Throwableの子供その2。
キャッチすべきではない重大な問題。
こちらはスローされる可能性が有ってもthrows節で宣言する必要はない。

という訳で、
例外機構としてはThrowableを継承したExceptionとErrorの2パターンに大別される。

ExceptionとErrorの仕様上の大きな違いはそれぞれ3行目に記述したthrows宣言の強制性である。
throws宣言が強制されない…というのはそのメソッドの外に出てもいいよ、という事なので、
必然的にcatchも強制されない。
Exception…コンパイル時にcatchまたはthrows宣言されているかが検査される。(検査例外)
Error…コンパイル時にcatchまたはthrows宣言されているかが検査されない。(非検査例外※)
という事である。

※ 厳密には例外ではないのかもしれないが。

Errorの方の説明をよく読むと「キャッチすべきではない」とある。
即ち、「強制されない」どころの話ではなくそもそもキャッチしてはいけないのだ。
キャッチしてはいけないのでキャッチさせてもいけない(≒throwsに書かなくて良い)訳ですな。
なのでコンパイラが検査する必要もないと。

なぜErrorを検査しないかについては言語仕様の方でさらなる言及がされている。
・いつ、どこで発生するか分からない (主にVM起因のエラーについてだろうか?)
・仮にキャッチしても回復が困難又は不可能
・そもそもErrorが発生してはならない
ということらしい。

「基本的に」キャッチすべきではない(※)理由については、最後まで伝播させるべきであるし、
下手にキャッチして潰されるのは困るということのようだ。

※ 「してはならない」ではない辺りイヤラシイ表現である。

つまり、いつ発生するかも分からないし、キャッチして欲しくないし、キャッチされたところでどうしようもないし、
そもそも通常は発生することがないから、
いちいちキャッチされているかthrows宣言されてるかは検査しないよってことのようだ。

ちなみにThrowable及びそのサブクラスが伝播して終了した場合のプログラム終了コードは1になります。
(通常は0)


というのが概ねの仕様であるらしいのだが、ここまで頑張って書いたけどまだ本題には入っていない。。。


【参考】
https://docs.oracle.com/javase/jp/8/docs/api/
https://docs.oracle.com/javase/specs/jls/se8/html/jls-11.html
コメント(0) 
共通テーマ:資格・学び

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。