たぶん、数日考えたくらいでは、Javaの例外を私がどうさばくのかという方針は決まらないだろう。
とはいえ、これに時間をかけているわけにもいかないので、自分の判定で60点くらいの納得ができればよいことにしてしまいたい。
最初の書いておくと、昨日の段階で自作のクラスはたいがいがExceptionを返すように作り替えてしまった。
勢いでやったと思うんだけど、やりすぎなのでまた作り方を変えるつもり。
その作り方を、ここで書きながら考えていこう。
まず、チェックされる例外、と、チェックされない例外、というものがJavaにある。
チェック例外・非チェック例外、検査例外・非検査例外など、呼び名は色々あるようだ。
英語だと、checked exception / unchecked exception、のようだ。
メソッド名の後ろにthrowsをつけ、そこにずらずら例外を書くのが「チェック例外」だと勝手に思っていたのだが、そうではないとのこと。
http://www.ne.jp/asahi/hishidama/home/tech/java/exception.html#h_checked_exception
チェック例外は、RuntimeExceptionを継承していない例外で、メソッド外に投げたいならばthrowsをつけてないとできないとのこと。
「そんな話から書くんか!」と思われるかもしれないが、知らないのだから仕方がない。
ようやく、定義らしきところにたどり着いた。
みんな「使い分け」の方に力が入っていて、そもそも何よ?が出てこなかったのだ。
http://docs.oracle.com/javase/jp/7/api/java/lang/Exception.html
はい、さっき書いたのと同じことが書かれてた。
関連するリンクに、Errorというのがあった。
http://docs.oracle.com/javase/jp/7/api/java/lang/Error.html
ここら辺まで眺めて、ようやくEffective Java 項目58の「checked exception / runtime exception / error」という分類になっているかがわかったというところ。
- 非チェック例外はRuntimeExceptionを継承したもの。
そうじゃないものはチェック例外。
異常だというのがエラー。 - 非チェック例外=実行時例外=RuntimeExceptionを継承しててthrowsなしでも伝わっていく。
- チェック例外=throws書いていないと伝わらないので、書かないならtry-catchで解決する。
これでよいのかな?
抽象的なのは疲れるので、今やっているところの話にしたい。
今使っているAPIは、こんな例外を投げてくるようだ。
- java.io.IOException
- android.os.RemoteException
- android.nfc.FormatException
継承図を見ると、どれもRuntimeExceptionが入っていないので、チェック例外ということになる。
例えば、NfcFクラスだと、以下が投げてくる。
- close()
呼ぶと、他でブロック状態になっていた要求がIOExceptionを投げられてキャンセルされる。 - connect()
既に他でconnectされていたら投げる - transceive()
I/O失敗か、キャンセルされたら投げる
close()はthrows対象になっているのは、close()処理がブロックされているときに他スレッドでclose()されたときに投げるからかな?
上記の例外は、けっこうどうしようもない感じだ。
自分のあずかり知らぬところで処理がキャンセルされたり、transceive()だと・・・何だろう?
NfcFクラスでは出てこないけど、その基底になるBasicTagTechnology。
これが、けっこうRemoteExceptionを返している。
NfcFではこれが現れないので、NfcF内で吸収していることになる。
RemoteExceptionは、AndroidのBinder関係の例外基底クラスのようだ(その割りに、継承してる人がほとんどいない)。
でも、これはこれでどうしようもない気配が漂っている。
BasicTagTechnologyなんか見てると、transceive()でRemoteExceptionが発生するとIOExceptionに差し替えているし、close()なんかは発生してもログを出すだけだったりする。
もうどうしようもないから、普通の流れで変なことをせずに終わろうとしている、という感じか。
そんなわけで、まず1つの基準。
RemoteExceptionはどうしようもないから、上に返さないでエラーにしてあげよう。
じゃあIOExceptionはどうするか。
これも、なるべく隠してあげる方がよいような気がしている。
今作ろうとしているのはNfcFっぽいクラスなんだけど、TagTechnologyを継承してthrowsがついているところは、そのままにして、そうじゃないで自分で作ったメソッドなんかは、なるべくエラー値で返してあげようか。
そうなると、どうエラーを返すか、とか、引数エラーはどうするか、とかが出てくる。
今日は力尽きたので、次回にしよう。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。