2014/09/02

[java]自分で60点くらいの例外処理を考えよう (1)

たぶん、数日考えたくらいでは、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 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。