文系seの備忘録

Excelの改行でひたすらスペースを打っていた機械音痴の文系seが日々の備忘録を綴る。

checked例外とunchecked例外

javaを使い始めて最初よくわからなかったのは例外処理。
try-catchとかthrowsとか聞いたことはあったけど、使い方は知らなかった。
紫本の最後の章である例外は見て見ぬフリをしてきた。
一番最後の章だし、ページ数少ないしまあいいかと思っていたけど、
「意外と例外処理が出題される」というのを耳にした。

それを聞いて焦り出し今月に入ってやっと例外のページを開いてみた。
しかし・・・ポンコツヘッドの持ち主である私は半挫折状態。

checked例外、unchecked例外?????
なんだそれ。

throwsの挙動を確認してみた -
この記事で挙動確認した際のソースを見返していて、
試しにthrowsのところを消してみた。
エラーになると予想していたが、ならなかったorz

それもそのはず、上記の例で書いたClassCastExceptionはunchecked例外なんですねーーーー
だからThrowsを書かなくてもコンパイルエラーにはならない。
明示的に記載することも可能。




以下はchecked例外、非checked例外について調べた結果です。

Java 入門 | 例外処理の使い方


チェック例外と非チェック例外の選択方針

例外処理しない
全てのメソッドに throws Exception を指定。
全ての例外は、チェック例外/非チェック例外の区別無く、コールスタックを伝播します。
適当なおまとめクラス(ファサードクラスなど)でログに吐けば終わりです。
ただし、これは例外処理の仕組みを放棄することになるので、システム全体で採用するには勇気が要ります。

全てチェック例外 (checked exception) とする
チェック例外は、呼び出し元で捕捉するか、さらに上位に投げるかしなければならないので、コード中に明文化することを強制できます。
但し、例外処理の不要なネストや、メソッドの内容からは不適切な実装レベルの例外がスローされて、
呼び出し元が混乱することがあります。
また、補足しても異常終了するほかない場合は、捕捉のコードは全くの無駄です。

全て非チェック例外 (unchecked exception) とする
非チェック例外は、例外処理が任意なので、コンパイルエラーが減り、呼び出し元のコードが状況に応じて判断できます。
但し、JavaDocなどの仕様書類に明文化されず、発生しても誰にも気付かれない恐れがあります。


チェック例外にするものと非チェック例外にするものについて取り決める•パッケージによって何れかしか使わないとする:
非チェック例外の場合は、コードで強制できないので、文書化方法を取り決める必要がありますが、パッケージで分けておけば、当該パッケージ開発時に、文書化の規約を取り決められます。

•回復可能であればチェック例外とし、回復不能であれば非チェック例外とする:回復不能の非チェック例外は、最上位の呼び出しまでスローされて異常終了するか、途中で捕捉されてロギングして異常終了するか選べます。
チェック例外の場合は、呼び出し元で処理して回復するように強制できます。

•正常なプログラムでは発生しないものを非チェック例外とし、外部の環境によって生ずるものをチェック例外とする:一般的な指針です。但し、プログラムの事前条件、終了条件、普遍条件は、「契約による設計 (DbC: Design by Contract)」と呼ばれるプログラミングスタイルで実現するものです。
J2SE 1.4以上では、キーワード assertion で実装できます。





Java例外メモ(Hishidama's Java Exception Memo)


Javaの文法との関連で言うと、非チェック例外はRuntimeExceptionを継承したクラス(例外)で、チェック例外はRuntimeExceptionを継承していないクラス(例外)。
つまり、チェック例外をメソッドの外にスローする際にはthrowsが必要になる。

そもそも「チェック」とは何かというと、「例外が発生したかどうかをチェックする必要がある」という意味だと思われる。
throwsが宣言されたメソッドを呼び出したら、throwsに書かれた例外をキャッチする処理(あるいはさらにthrowsで呼び出し元に渡す)を書かなければならない。
「例外をキャッチするようコーディングする」=「例外の発生をチェックしている」ということになるのだろうか。
ではRuntimeExceptionを継承したクラス(非チェック例外)はキャッチ(チェック)しなくていいかというと、そうなのか?
(文法上はキャッチすることは出来る)

最初は、チェックという言葉のニュアンスから、「何らかのチェックをした結果として投げるのがチェック例外」だと思っていた。
とするとそんなのはほぼ全てに該当する訳で、「非チェック例外って何者?」と疑問だった。
「実行時例外」はRuntimeExceptionの日本語訳だろうか。これも、例外は常に実行時に発生するので、違和感を感じさせる名前だ^^;
といった事が曖昧に感じられる為、個人的にはチェック例外・非チェック例外という言葉は極力使わないようにしている。


ただ、チェック例外と非チェック例外という区分がなぜあるのか・その目的は?という点から考えると、
キャッチしてもどうしようもないもの(≒コーディング上のバグ)は非チェック例外とする。
◦呼び出し元を透過(スルー)してアプリケーションを異常終了させる。
実行時の状態(環境)によっては起こり得る(指定されたファイルが見つからないとか)はチェック例外とする
◦呼び出し元で例外処理をすべき。

ということかもしれない。
チェック例外は、「異常系正常処理」(起こることが想定される(実際に起こり得る)異常に対する処理)な気がする。