Java 7では、それらを明示的に閉じるのではなく、自動リソース管理を使用して、リソースが閉じられ、例外が適切に処理されるようにします。例外処理は次のように機能します。
tryの例外| クローズの例外| 結果
----------------- + -------------------- + ----------- -----------------------------
いいえ| いいえ| 通常どおり続行します
いいえ| はい| close()例外をスローします
はい| いいえ| tryブロックから例外をスローします
はい| はい| close()例外をメイン例外に追加します
| | 「抑制された」として、主な例外をスローします
うまくいけば、それは理にかなっています。Inは、次のようなきれいなコードを許可します。
private void doEverythingInOneSillyMethod(String key)
throws MyAppException
{
try (Connection db = ds.getConnection()) {
db.setReadOnly(true);
...
try (PreparedStatement ps = db.prepareStatement(...)) {
ps.setString(1, key);
...
try (ResultSet rs = ps.executeQuery()) {
...
}
}
} catch (SQLException ex) {
throw new MyAppException("Query failed.", ex);
}
}
Java 7より前は、参照のnullをテストするのではなく、ネストされたfinallyブロックを使用するのが最適です。
私が示す例は、深いネストでは見苦しいかもしれませんが、実際には、適切に設計されたコードは、接続、ステートメント、および結果をすべて同じメソッドで作成することはおそらくありません。多くの場合、ネストの各レベルでは、リソースを別のメソッドに渡し、別のリソースのファクトリとして使用します。このアプローチでは、aからの例外は、ブロックclose()
内からの例外をマスクします。try
これは克服できますが、コードがさらに乱雑になり、Java7に存在する「抑制された」例外チェーンを提供するカスタム例外クラスが必要になります。
Connection db = ds.getConnection();
try {
PreparedStatement ps = ...;
try {
ResultSet rs = ...
try {
...
}
finally {
rs.close();
}
}
finally {
ps.close();
}
}
finally {
db.close();
}