4

まず、よく使われているトピックについて質問して申し訳ありません。たくさんの質問に出くわし、finallyブロックでリソースを閉じるメソッドからの潜在的な例外を飲み込む(キャッチして無視/ログに記録する)ことを提案する回答があります。一般的に受け入れられているパターンのようです。しかし、私はまだ誰もその理由を説明するのを見ていません。ほんの一例です:Try-catch-finallyそしてもう一度trycatch

finallyブロックからスローされた例外は、対応するtryブロックでスローされた例外を「マスク」することを理解していますが、これがなぜ悪いことなのかわかりません。例えば:

Resource r = new Resource();
try {
    r.use();
    other();
} finally {
    r.close();
}

私の現在の理解は次のとおりです。

  1. 例外をスローするだけの場合closeは、絶対に飲み込みたくありません。
  2. 両方とも例外usecloseスローする場合、それはおそらく同じ根本的な理由であり、どちらの例外が伝播されるかは問題ではありません(どちらにも同じように役立つ情報が含まれていますか?)。
  3. 両方とも例外otherをスローする場合、2つの無関係な問題があります。closeおそらく最初に発生したものが伝播するはずですが、最初の例外が2番目の例外を引き起こしたことを示唆する理由はありません(ありますか?)。

私は何が間違っていますか?

4

1 に答える 1

3

closeだけが例外をスローする場合、それを飲み込みたくないことは間違いありません。

それは正しい!

useとcloseの両方が例外をスローする場合、それはおそらく同じ根本的な理由であり、どちらの例外が伝播されるかは問題ではありません(どちらにも同じように役立つ情報が含まれていますか?)。

あまり。の例外はtryNullPointerExceptionまたはOutOfMemoryError問題の性質を説明する実際のI/O例外である可能性があります。I / O例外であっても、エラーによってストリームが一貫性のない状態のままになっている可能性があります(または、ストリームを途中で閉じている可能性もあります)。呼び出すと、「ストリームはすでに閉じられています」、「内部エラー」など、まったく異なるエラーが発生close()する可能性があります。

システム内の1つのエラーは、他の数十をカスケードする傾向があり、非常に無関係に見える場合があります。根本原因の最初の例外を常に探します。残りはただのゴミです。良い例は、初期化に失敗し、オブジェクトを一貫性のない状態のままにしたことです。後でNullPointerExceptionどこにでもsが表示されますが、実際の問題はずっと早く発生しました。

otherとcloseの両方が例外をスローする場合、2つの無関係な問題があります。[...]最初の例外が2番目の例外を引き起こしたことを示唆する理由はありません(ありますか?)ので、どちらもそうします。

実際には、両方の例外はインポートですが、最初の例外の方がおそらくより適切です。解決?Java7のAutoCloseableリソースとtry-with-resourcesイディオムを使用します。クリーンアップ中に例外が発生した場合、抑制されたものとして元の例外にアタッチされます。

class Resource implements AutoCloseable  //...

その後:

try(Resource r = new Resource()) {
    r.use();
    other();
}

例外は次のようになります。

MyException: Exception in use()
at Resource.use(Main.java:11)
at Main.main(Main.java:16)
    Suppressed: java.lang.RuntimeException: Exception in close()
        at Main.close(Main.java:6)
        at Main.main(Main.java:17)
        }
于 2012-10-02T20:53:18.100 に答える