高レベルの計算を実行するために低レベルまたはクラスに委譲する高レベル コードを呼び出すInputStream.close()
、または高レベル コードであるコード。OutputStream.close()
InputStream
OutputStream
例外をスローするかどうか
何をするかについては、3 つの選択肢しかありません。
- 例外をキャッチして飲み込み、破棄します。
- 上に伝播させましょう。
- 例外をキャッチし、別の種類の例外をスローします。この場合、通常は連鎖例外を使用します。
最後の 2 つのオプションは、コードが例外をスローするという点で似ています。したがって、この質問は実際には、コードがいつ例外をスローする必要があるかという質問の特殊なケースです。このコンテキストでのその質問に対する正しい答えは、次のとおりです。代替手段が、コードの事後条件を満たさないか、コードの不変条件を維持することである場合に限ります。事後条件は、メソッドの目的を指定します。不変条件は、クラスの特性を指定します。
したがって、close()
例外をスローすることで、メソッドが本来すべきことを実行できなくなるかどうかを自問する必要があります。
- メソッドがその仕事をするのを妨げない場合、正しいことは例外を飲み込むことです。多くの人があなたに言うことにもかかわらず。
close()
スローによってメソッドがジョブを実行できず、メソッドが をスローする可能性がある場合は、IOException
何もできず、例外を上に伝播させるだけです。
close()
メソッドがジョブを実行できないが、メソッドが をスローしない可能性がある場合は、IOException
をキャッチしIOException
て別のクラスの例外として再スローし、スローされた例外IOException
の原因として を記録する必要があります。
InputStream.close()
例外のスローによって計算の成功が妨げられる状況を私は知りません。への呼び出しは、関心のあるデータを読み終わった後close()
に自然に発生します。
ただし、出力ストリームは、内部 (Java コード内) または下位レベル (オペレーティング システム内) のいずれかで、出力先に書き込まれるデータをバッファリングできます。したがって、(例外をスローせずOutputStream.close()
に)が正常に戻るまで、出力ストリームへの書き込み操作が実際に実際の出力になったことを確認することはできません。したがって、 によってスローされた例外は、書き込みの失敗と同じように扱う必要があります。OutputStream.close()
メソッドは、その不変条件を維持する責任があります。close()
例外がスローされた場合、クリーンアップまたはロールバック操作が必要になることがあります。例外を上方に伝搬させたい場合でも、そのコードを のcatch
orfinally
節に入れる必要があります。IOException
catch 句を使用していて、それを伝播したい場合は、再スローする必要があります。
例外をログに記録するかどうか
例外をログに記録するようアドバイスする人もいます。これはほとんどの場合、悪いアドバイスです。ログ メッセージは、プログラムのユーザー インターフェイスの一部です。役に立たない言い回しは、ログ ファイルを読んでいるユーザー (「ユーザー」にはシステム管理者を含みます) の注意をそらし、混乱させる可能性があるため、基本的に、何かをログに記録するかどうかを常に自問する必要があります。ログに記録されたすべてのメッセージは、何らかの有用な目的である必要があります。それぞれが、ユーザーの意思決定に役立つ情報を提供する必要があります。
失敗したことを具体的に報告することclose()
はほとんど役に立ちません。ユーザーの意思決定にどのように役立つでしょうか? 例外によってメソッドの動作が妨げられなかった場合、問題はなく、ユーザーによるアクションは必要ありません。close()
プログラムがストリームに失敗し、それが問題である場合、ユーザーは何ができるでしょうか?
通常、低レベルのコードはログ記録をまったく担当しません。代わりに抽象的な操作を実行し、例外をスローしてプログラムの上位レベルの部分に失敗を報告します。通常、ストリームを閉じるコードはかなり低レベルであるため、それを検出するコードclose()
は低レベルすぎてログを記録できません。
失敗したという特定の事実がclose()
役立つことはめったにありません。役に立つのは、メソッドが実行するはずの抽象操作が失敗したことを知ることです。これは、メソッドに「クローズに失敗しました」と正確に報告させるのではなく、より高いレベルのコードに予想されるすべての例外をキャッチさせ、操作が失敗したことを報告させることで実行できます。