2012/10/07

Exception が発生した時の LogCat の読み方 (2)

穀風: Exception が発生した時の LogCat の読み方 (1) では、最もシンプルな LogCat の読み方を書きましたが、実際はそんなに単純な Exception が出ることは稀です。
今回はもう少し現実的な Exception を見てみたいと思います。

サンプルは前回と同様のものです。


Button2 を押すと、以下のような Exception が発生します。


上から見ていくと、IndexOutOfBoundsException が発生したことがわかります。
どんな Exception なのかは調べてみて下さい。

さらに、次の行を見ていくと、ArrayList.java の 257行目が発生源のようです。
そんなコードを書いた覚えはありません…

これ、当然といえば当然です。
Exceptionというのは、メソッドの使い方を間違えた場合などに呼び出し元にそれを通知するために使うものですから、一般的には自分の書いたコードではないところで発生するのです。

 というわけで、誤った呼び出し方をしている場所を探していきます。
上から見ていくと、 一番最初に自分の書いたコードが出てくるのが、ArrayList.get を呼んでいる MainActivity.java の 39行目です。
ここが問題のようですね。

39行目を確認してみましょう。

37行目でリストを初期化した直後なので、当然リストは空です。
その空のリストから要素を読み出そうとしているので、ArrayList が「その使い方は間違っているよ。」と、IndexOutOfBoundsException を発行しているわけです。


このように、上から追いかけていって、自分の書いたコードが出てきたところをチェックするのがデバッグ時の常套手段です。

次はスレッドを分けた場合の Exception を見てみたいと思います。
穀風: Exception が発生した時の LogCat の読み方 (3)


おまけ
完全に余談ですが、Exception (例外)のような機能を持たないC言語などでは、メソッドの戻り値でエラーコードを返したりしてメソッドが正しく使用されたかどうかをチェックすることがあります。
エラーコードを返されて、すぐそれに対する処理を行える場合は良いのですが、さらに上位に判断を委ねたい場合は、その上位にもエラーコードを返さなければなりません。
この時、同じコードを返すべきでしょうか?別のコードに変換すべき?
これはなかなか難しい問題です。

大抵、モジュール毎にエラーコードはまとめて定義するので、同じモジュール内であれば、同じエラーコードを返せば良いです。
しかし、AというモジュールがBというモジュールを使用している場合はどうなるでしょうか?
Bの返したエラーコードをAより上のモジュールに通知したい場合、Aのエラーコードに変換してやらねばいけません。

Exception を使用すれば、自分のところで判断できないエラーは上位にそのまま返してあげれば良いです。RuntimeException であればエラーチェックをする必要さえありません。
最初はとっつきにくい Exception ですが、きちんと使用するととても便利なのです。


0 件のコメント: