第9章 Java 7 の機能を復習する : 問題 2 : 抑制された例外
問題
以下のコードを try-with-resources 文を使わず、かつclose
メソッドでスローされる例外を抑制された例外として元の例外に追加するように実装せよ。
■ try-with-resources 文を使った例
try (BufferedReader in = Files.newBufferedReader(Paths.get("/usr/share/dict/words")); BufferedWriter out = Files.newBufferedWriter(Paths.get("/tmp/out.txt")) ) { String line; while ((line = in.readLine()) != null) { out.write(line.toLowerCase()); out.newLine(); } }
解答
IOException
がスローされるのは、大きく分けて以下の4つのケースである。
in
ないしout
のオープン- ファイルを読み書きするメインパート
out
のクローズin
のクローズ
そこで、これら4つのケースで発生した例外を覚えておくことにする。
IOException openException = null; // リソースのオープンで発生した例外 IOException mainException = null; // 中心となる例外 IOException inCloseException = null; // in.close() で発生した例外 IOException outCloseException = null; // out.close() で発生した例外 try { BufferedReader in; try { in = Files.newBufferedReader(Paths.get("/usr/share/dict/words")); } catch (IOException ex) { openException = ex; throw ex; } try { BufferedWriter out; try { out = Files.newBufferedWriter(Paths.get("/tmp/out.txt")); } catch (IOException ex) { openException = ex; throw ex; } try { String line; while ((line = in.readLine()) != null) { out.write(line.toLowerCase()); out.newLine(); } } catch (IOException ex) { mainException = ex; throw ex; } finally { try { out.close(); } catch (IOException ex) { outCloseException = ex; throw ex; } } } finally { try { in.close(); } catch (IOException ex) { inCloseException = ex; throw ex; } } } catch (IOException ex) { // ex は openException, mainException, inCloseException, outCloseException のいずれか if (openException != null) { // mainException, outCloseException は発生していない if (inCloseException != null) openException.addSuppressed(inCloseException); throw openException; } if (mainException != null) { if (inCloseException != null) mainException.addSuppressed(inCloseException); if (outCloseException != null) mainException.addSuppressed(outCloseException); throw mainException; } if (inCloseException != null && outCloseException != null) { inCloseException.addSuppressed(outCloseException); throw inCloseException; } throw ex; }
なんというステップ数、可読性は最悪。
try-with-resources 文は偉大だ!