- - PR -
NumberFormatException が非チェック例外なのはなぜ?
| 投稿者 | 投稿内容 | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2003-11-20 13:18
例外について、「実践 J2EEシステムデザイン」って言う分厚い本の中で、
「チェックされる例外は例外の数が少ないうちは、とてもうまくいき素晴らしいもの だと感じられるが、例外の数が多くなるとむしろ邪魔になってくる。」 ってなことを言っています。 例外をcatchするコードがあまりに多いとコードの可読性は低下しネストした例外処理は ミスを犯す可能性が高い(途中で例外が途絶えたり)。さらにチェックされる例外を catchして新しい例外でラップしてまた投げる、またはメソッドの宣言にthrowsを 書いてただ呼び出し元へと投げられるような無意味なことが多い。 ということでこの本の著者は むしろRuntimeExceptionを標準にした方が良いのではないかと提案しています。 で、どうしても呼び出し側に知らせたい場合のみ、チェックされる例外にすれば良いと。 僕もこの著者の意見に賛成です。 大抵例外を処理できるのなんて一番頭の呼び出し元ですもの。 そう考えるとWebアプリケーションで、チェックされる例外を 自分で定義するような場面ってないんじゃないかと思います。どうせ呼び出し元に 向かってスルーしてくだけなんだから。たとえばユーザの入力ミスを表す InvalidInputExceptionってのを定義するとしても入力チェックでこの例外を投げたら 処理できるのなんてエラー画面だす処理をするクラスだけであって、このクラスまで ずっと例外をスルーしてくだけじゃないかと。もしもInvalidInputExceptionを チェックされる例外にしたら入力チェックを行うクラスからエラー処理するクラスまで 全てにthrowsを書かなければならず、無意味だと思います。 なので、現実的に考えてNumberFormatExceptionを入力値エラーの判定に使ったって 良いと思います。概念的にRuntimeExceptionをcatchするのは良くないからとかじゃなく 必要だったらcatchすりゃいいし、その方がシンプルに出来るならそれでいいんじゃ ないかと思います。 ということで、チェックされる例外は大抵おせっかいなのであまり好きではないの ですが、この機能もコンパイラで出来る限りプログラミングのミスを減らそうって いう試みなんでしょうね。 例えばif文の==って書くのを=って書いたらコンパイルエラーになると同じように。 | ||||||||||||
|
投稿日時: 2003-11-20 14:58
unibon です。こんにちわ。
私も同感です。 これを避けるためにも、例外の必要性がないものは、 例外以外の戻り値などで返すべきだと思います。
これもこの著者に同感です。
これには納得いかない感じがします。 この本は読んだことがないのでニュアンスは分からないのですが、 起きる可能性のあるエラーが非チェック例外でいきなり throw されても、 受けるほうは困ってしまいます。 javadoc の @throws に頼らなくても、メソッドが throw する可能性がある非チェック例外を すべて網羅できるような環境があればよいのですが。 なお、その後考えていたら、 NumberFormatException が非チェック例外な理由がなんとなく分かりました。 NumberFormatException はコンストラクタの引数チェックなどで使われることが多く、 コンストラクタ内で起きたエラーを返すのに戻り値の仕組みを使おうとすると、 別途 getter 等のアクセッサを呼ばなければならず不便であり、実用的ではありません。 したがって例外で返さざるを得ないのですが、この著者の意見のように、 チェック例外だといちいち catch しなくてはならず面倒になります。 それで非チェック例外に落ち着いているのだと思います。 | ||||||||||||
|
投稿日時: 2003-11-21 07:57
例外の生成はものすごくコストがかかるので、毎回発生するような数値型のチェックにparseInt()はよろしくないですね。(それにparseInt()は全角数値とかキリル文字とかロシア文字とか通してしまいますし。)
SunはparseInt(String)でNumberFormatException投げるぐらいだったらNumber系クラスに boolean isVaild(String) みたいなメソッド用意しろって感じですな。 | ||||||||||||
|
投稿日時: 2003-11-21 12:10
そうですね。ところで、キリル文字の数字って使えます?漢数字とギリシャ数字を受け付けないのに。(キリル文字の数字がどれだかわからないので...) パフォーマンスを重視するなら、isVaild(String)の場合、チェックが二重になってしまうので 戻り値をラッパ型/nullにしてくれたほうがいいかな。 あと、チェック例外と非チェック例外の使い分けに関してはEffective Javaには 次のようにかかれていました。
#補足 引用文中の「その負荷」とは、プログラマが例外をハンドリング(throws宣言、try-catch)することを強制されることです。 [ メッセージ編集済み 編集者: Wata 編集日時 2003-11-21 12:50 ] | ||||||||||||
|
投稿日時: 2003-11-21 12:43
または、代替案として、isValied()は指定したロケール(またはデフォルトロケール)でfail-fastでチェック(無効な文字が出た所で抜ける)し、parseInt()は指定したロケール(またはデフォルトロケールで)無理やり変換してしまうというのもありかな。 | ||||||||||||
|
投稿日時: 2003-11-21 15:16
意見センキュー、unibonさん
引用: ---------------------------------------------------------------------------- unibonの書き込み (2003-11-20 14:58) より: 引用: ------------------------------------------------------------------------ やまろうさんの書き込み (2003-11-20 13:18) より: ということでこの本の著者は むしろRuntimeExceptionを標準にした方が良いのではないかと提案しています。 で、どうしても呼び出し側に知らせたい場合のみ、チェックされる例外にすれば 良いと。 ------------------------------------------------------------------------ これには納得いかない感じがします。 この本は読んだことがないのでニュアンスは分からないのですが、 起きる可能性のあるエラーが非チェック例外でいきなり throw されても、 受けるほうは困ってしまいます。 javadoc の @throws に頼らなくても、メソッドが throw する可能性がある 非チェック例外をすべて網羅できるような環境があればよいのですが。 ---------------------------------------------------------------------------- とのことですが、「javadoc の @throws」以下のことには賛成なんですけど、 「納得いかない」ってとこで、 えーと、「実践 J2EEシステムデザイン」は先輩から借りて読んだので今手元にない のですが(なんせ6500円もするんで) この本の著者が言いたいのは、チェックされる例外を投げられても、呼び出し側が何も対処出来るようなことがないような例外なのにチェックされる例外を投げてる場面が多いんじゃないか?それなのにtry-catchまたはthrowsを書くことをコンパイラによって強制されて やんなっちゃうよっていうようなニュアンスなんだと思います。呼び出し側で対処出来なくてthrowsを最初の呼び出し元まで書いてくだけのような例外だったらRuntimeExceptionにしてもいっしょですよね! ということで、むやみにチェック例外を使いすぎてるからRuntimeExceptionを標準にして チェック例外を作る時は呼び出し側が対処できるかってことを開発者に意識させようぜという感じなんじゃないですかね。 [ メッセージ編集済み 編集者: やまろう 編集日時 2003-11-21 15:21 ] | ||||||||||||
|
投稿日時: 2003-11-21 15:57
unibon です。こんにちわ。
すみません。著者の意図を誤解していました。それなら納得できます。 「呼び出し側が何も対処出来ない」場面ならば、非チェック例外である、 IllegalStateException や IllegalArgumentException や NullPointerException 等を、 バシバシ投げるのは好ましいことだと思います。 ただ、「呼び出し側が何も対処出来ない」かどうかの判断が難しいと思います。 たとえば assert があって assertion を満たさない場面なら、 「呼び出し側が何も対処出来ない」と思いますので、 非チェック例外は投げても良いでしょう。 しかし、たとえば NumberFormatException が投げられるような場面では 「呼び出し側」は、「入力が正しくありません」とダイアログを出したり、 そのような Web のレスポンスを返して対処することは可能です。 やはり parseInt/parseDouble や new Integer(String)/new Double(String) をする前には、 それらのメソッドとは別のやりかたで、引数のチェックは済ませておくべきなのでしょうか。 #と、なんだか最初の質問に戻ってしまいました。 | ||||||||||||
|
投稿日時: 2003-11-21 17:17
私の推測なのですが、NumberFormatException は IllegalArgumentException の
サブクラスであることから、Integer#parseInt メソッド等の引数には解析可能な文字列を 渡すことを前提としているのではないでしょうか? #例えば、数字しか入力されない項目から取得した文字列であれば例外をキャッチする #必要はないですよね? もし、解析可能かどうか分からない文字列を解析する場合は java.text.NumberFormat クラスの parse メソッドを使う、ということなのではないでしょうか? # parse メソッドが発生させる java.text.ParseException はチェック例外。 | ||||||||||||
