- ベストアンサー
例外処理の基準とは?
- 例外処理には、特定の例外の種類よりも広範囲な例外をキャッチする「Exception」という基準があります。
- しかし、適切な例外処理を実現するためには、できるだけ具体的な例外をキャッチする方が好ましいです。
- 具体的な例外をキャッチすることで、エラーの原因を特定しやすくなり、デバッグやトラブルシューティングが容易になります。
- みんなの回答 (1)
- 専門家の回答
質問者が選んだベストアンサー
困リ度3なのに、 こんなに遅いスレッドでごめんね だって、これ見つけたの今だから・・。 >を読むと「それなら、どんな例外でもすべて"(Exception e)"でcatchすればいいじゃん」と思うので>すが駄目ですか? >もし駄目ならどんな基準でExceptionを選んでいるのですか? だめじゃないですよ。 (例としてあまりよくないかもしれないけど・・・) たとえば、ユーザがテキストフィールドに 数字文字列を入力するとします。 あるメソッド public void foo(String text) throws Exception { があったとします。 [読み込み]ボタンが押されたときに、 このメソッドは先ほどユーザが入力した文字列を 引数にして呼ばれるとします、 fooメソッドは ユーザが入力した数字をファイル名に含むようなファイルから情報を取得するとします。 (例) ユーザが入力したのが 23なら hoge23.dat から情報を取得する。 hoge~.datは世代管理されたファイルで、 作られた順番で連番がつけられているとします。 なので、~の部分に数字文字列以外がくることは 仕様上ありえません。 ユーザが入力した文字列に数字文字列以外が存在すれば、 正常系のエラー処理するとします。 fooメソッドの最初に Integer numObj = new Integer(引数の文字列) int number = numObj.parseInt(); というコードがあると、引数の文字列に 数字文字以外があると Integer numObj = new Integer(引数の文字列) の new Integer(引数の文字列) 部分で NumberFormatExceptionが投げられます。 String型をとるIntegerのコンストラクタは public Integer(String s) throws NumberFormatException とあり、 throws NumberFormatException があるので、NumberFormatException をcatchしているかどうかのチェックを コンパイラに要求しますが、 fooメソッドはNumberFormatExceptionの親の Exceptionがthrows節にあるので、 fooメソッドの定義の中の Integer numObj = new Integer(引数の文字列) の部分をtry~catchで囲む必要はないです。 囲まなければfooメソッドの中ではそれ以降の処理は 実行されず、 fooメソッドの呼び出し式の部分が NumberFormatExceptionを投げます。 Integer numObj = new Integer(引数の文字列) の部分で例外処理したいのであれば、別に try~catchで囲んでもいいですが その場合、fooメソッドの中では catchの中を実行した後、 try ~ catchの次のコードから実行されます 今回はfooメソッドの中ではtry~catchしないものと して話をすすめます。 一方、ユーザが首尾よくまともな数字文字列 "23"を入力してくれたとして、 hoge23.datが存在しなかったとします fooメソッドの定義の中では以下のコードがあるとします。 File hogeFile = new File("C:\\~\\hoge" + number + ".dat"); //hoge23.datが存在しなければ if( !hogeFile.exist() ) { //FileNotFoundException();を投げる!! throw new FileNotFoundException(); } //そして、この↓でfooメソッドは、 //本来やりたかったファイルの情報を読み込む処理を //するのであった。 ふう、ちょっとつかれました。 書くのも大変ですが、読むのも大変ですね。 もうすこしがまんしてね。 さて、まえおきが長くなりましたが、 fooメソッドが呼び出してる部分はどんな感じでしょうか? きっと、こんな感じだとおもいます。 ちなみに、存在しない世代番号が入力された 時は、現在、存在するあるもっとも大きな世代番号を メッセージボックスに出す仕様だとします。 読み込みボタン.addActionListener(new ActionListener(){ // String text = テキストフィールド.getText(); try { foo(text); } catch(NumberFormatException nume) { //入力が不正である旨をユーザに通知する処理 ・ ・ ・ } catch(FileNotFoundException nume) { //現在、存在するあるもっとも大きな世代番号を //通知する処理 ・ ・ ・ } catch(Exception e) { //想定外の例外なので、その、プロジェクトで、 //共通のやり方があればそれをする ・ ・ ・ } }); 以上、なんのエラーかを明らかにして、 それに応じて処理をわける必要があったから、 こうします。 普通は、テキストフィールドに数字以外に 入力できないようにするとか、 テキストボックスは使わずに、 現存する世代番号をリストボックスに陳列させて 選ばせるとかするでしょう。 なので、あまり良い例ではありませんが、 一応、説明に使う分には十分だと思います。 >だからと言ってthrow ~ catchを入れないとJBuilderが怒>るんですよね…。 throw ~ catchじゃなくて、 try ~ catchですね (あげあし、じゃなくて確認しただけね) メソッドやコンストラクタの宣言に throws節があると、 呼び出し側では、 そこにリストされているチェックされる例外クラス について同じか、または、その親をcatchしないと コンパイラにおこられます。 呼び出し側のメソッド自体が そこにリストされているチェックされる例外クラス について同じか、または、その親 をthrows節の中にもてば、 呼び出し側のさらに、上の呼び出し側に catchすることを要求するので、 呼び出し側ではcatchしなくてもコンパイラに おこられません(してもいいけどね) チェックされない例外 RuntimeException の一族だったような、 はっきり言って記憶はあいまいです チェックされない例外 チェックされる例外 のチェックは実行時ではなくて、 コンパイラにチェックを要求するかしないか という意味です。 以上 あとは、自分で勉強して~ つかれました、おわりで~す。 これ以上は無理。
お礼
わぁー、こんなに熱烈な回答は初めてです。 なるほど、NumberFormatExceptionやFileNotFoundExceptionのような 予想される例外の場合は処理を分けるのですね。 そして、Exceptionは他のXXX.Exceptionたちの親玉なんですね。 JBuilderにこっぴどく怒られる理由もよく分かりました。 これからも自分で勉強してみます。 本当にお疲れでしょう? 目とか大丈夫ですか? ありがとうございました!