例外処理 (J)
はじめに
I/Oに関しては、プログラム外とのやりとりになります。ということは、正しいプログラムであっても、外部の事情で当初の意図どおり動けないことがあります。
Java では、そのような処理は例外とし扱い、java.io.IOException などについては、例外の扱いの明確化を要求します。 ネットワークアクセスの場合も、普通のファイル I/O の場合も、しばしば例外処理が要求されます。
Java では、
try-catch-finally
ブロックを用いて、例外処理するか- メソッドに
throws Exception
宣言をして、例外が起きることを明示するか
のいずれかの対処が必要です。
例外処理は、こんな感じ。catch
節とfinally
節のどちらか一方だけでも大丈夫です。
try {
// 例外を起こすかもしれない処理
// を含んだブロック
} catch (Exception1 e1) { // try ブロック内で Exception1 型の例外が起きたら、
// ここで捕まえる。対象の例外オブジェクトは e1 ね。
// 例外処理内容1
} catch (Exception2 e2) { // try ブロック内で起きた例外が前のハンドラで捕まらず、
// ここまでもれてきたら、Exception2 型なら受け取るよ
// 例外処理内容2
} finally { // finally 節
// 例外の有無に関わらず、実行して欲しい事柄を書く場所
}
これで、例外に応じた処理を書くことができます。 ちなみに、java.io.FileInputStream のコンストラクタで起きる java.io.FileNotFoundException は、
- java.io.IOException の子クラスで、
- java.lang.Exception の孫クラスでもあるので、
これらのクラスを catch 節に書いた場合も FileNotFoundException
は catch できます。
複数のクラスの exception をまとめて処理したい場合は以下のように記載可能です。
} catch (Exception1 | Exception 2 e) {
// Exception1, Exception2 に共通の型操作
}
catch-finally 節の利用法
catch 節に関する使い方のおすすめは以下のとおり。
- 一般的な利用としては、Exception があった理由を表示して、終了する。あるいは、ユーザに次の処理を入力してもらって、次の動作を行う。
- 絶対、Exception が起きないと確信していたら、絶対起きない旨書いておく。
} catch (Exception e) {
throw new Error("This SHOULD NOT occure!"); // あるいは、 assert false;
}
- デバッグ中なら、下記のようにバグ情報出力をおこなうとよいでしょう。
} catch (Exception e) {
e.printStackTrace();
}
-
あるいは、今回のように例外をそのまま throw する。例外が起きたら、ターミナルに状況が表示されます(先の
printStackTrace()
相当ですね)。 -
やってはいけないこと: 良くわからないからといって、見なかったことにする。先送りしても、別のバグと混ざって分かりにくくなるだけです。自分で自分にトラップ仕掛けるようなものです。絶対止めましょう。
} catch (Exception e) {
/* みなかったことにしよう。。。 */
}
/* 事態は、さらに混迷を深める */
ちなみに、finally 節のよくある利用法は、
- 後始末で行うような、ファイルを close() したり、ネットワーク処理で使った socket や port を閉じたり
というのが普通です。ただ、最近は次に紹介する記法をつかうことが多いようです。
Automatic Resource Management
I/O では、stream を開いて、一連の処理をした後で、例外の有無にかかわらず stream を閉じるってプログラムの形は多くなります。
このようなプログラムは、
try ( /* stream などを開く */ ) {
/* 一連の処理 */
} /* catch 節や finally 節も記述可能 */
という形で書くこともできます。皆さんに見せたプログラムでは、こちらの記法を採用しています。
実は、InputStream や Socket などは、すべてjava.lang.AutoCloseable interface を継承していて、close()
メソッドで自動資源解放ができるような統一規格になっています。