『Effective Java』より (Joshua Bloch)
- 例外的な条件にのみ例外を使用します (通常の制御フローには使用しないでください)。
- 回復可能な状態にはチェック例外を使用し、プログラミング エラーには実行時例外を使用します。
- チェック例外の不必要な使用を避ける
チェック例外を避ける。
http://www.mindview.net/Etc/Discussions/CheckedExceptions
http://www.ibm.com/developerworks/java/library/j-jtp05254/index.html
- 多くの場合、チェック例外は欠陥のある機能と見なされます。それは悪い考えではありませんが、人々はそれらの使い方を本当に理解していません.
- Spring、Hibernate などの Java フレームワークは、ほとんどの場合、未チェックの例外をスローします。
- C# は、意図的にチェック例外を実装していません。スカラも。
- キャッチできないのは、チェックされていないからではありません。
- 翻訳できないのは、チェックを外したからではありません(ラップしてください)。
- それが契約の一部ではないことは、チェックされていないからではありません。実際、チェックされていない例外をスローするメソッドを宣言できます。
- チェックされた例外は、クライアントとライブラリ間の結合を増加させます
理解しておくべき非常に重要なことの 1 つは、どのコードでも例外が生成される可能性があるということです。
メソッドが IOException のスローを宣言しているため、他の例外をスローできないというわけではありません。他のランタイム例外 (汎用またはカスタム) をスローできます。チェック例外では、開発者は逆に考える傾向があり、IOException をキャッチすればすべての例外ケースが処理されると考えがちですが、そうではありません。
コンパイル時のみの機能
チェックされた例外をキャッチまたは再スローするのを忘れた場合、コンパイラのみが通知します。実行時には違いはありません。
これは、型消去のトリックを使用することで、メソッド コントラクトの一部でなくても、チェック済みの例外をスローできることを意味します。
ここで SneakyTrow と呼ばれるこのトリックの例を見つけることができます:
https://stackoverflow.com/a/4890489/82609
Lombok は、メソッド署名でチェック済み例外を宣言する必要がないように、メソッドに付ける @SneakyThrow アノテーションも提供します。
クラス クライアントが例外から回復できる可能性が高い場合にのみ、チェック済み例外を使用します。
これは、Sun の推奨事項です。
基本的に、データベースに接続しようとするとチェック例外がスローされ、再試行戦略コードは接続試行時にこれらのチェック例外をキャッチします。再試行回数を超えると、再試行戦略は未チェックの例外をスローします。つまり、回復戦略は既に試行されているため、回復可能な例外ではありません。ちなみに、Spring RetryTemplate を使用できます。
例外コードを避ける
例外タイプは、フロー制御の決定に十分なはずです。例外の解析やフロー制御は、役に立たないコードを作成するだけです。例外コードがある限り、例外タイプを追加します。
早く失敗する
すべての回復不可能な例外が IHM レイヤーにスローされるようにします。チェックされた例外を宣言するフレームワークを使用していて、それらの回復戦略がない場合は、チェックされていない例外にそれらをラップすることを躊躇しないでください。
回復できない場合は、「キャッチ アンド ログ」を行うべきではありません。さらに悪いことに、「キャッチしてnullを返す」ことはすべきではありません。これにより一貫性のないソフトウェアが生成され、プログラムの少し後で別の例外が発生する可能性がありますが、その理由を理解することはできません。null を返すと、後で NullPointerException が作成されるだけです。
IHM レイヤ テクノロジには、例外ハンドラ/マッパーがある場合があります。Web IHM レイヤーには例外マッパーがあり、「この例外は 404 エラーを生成します」と言うことができます。
機能的アプローチ
参考までに: 関数型言語では、フロー制御に例外を使用することはよくないと考えられています。通常、例外をスローする代わりに、Either[Error,MyResultType] のような「拡張型」を返します。
返されるインスタンスはエラーまたは成功のいずれかであり、成功は MyResultType インスタンスが返されます。
例外はフロー制御に対してパフォーマンスがありません
例外の作成にはコストがかかります (スタックトレースの作成)。if、else... を使用した通常のフローよりもはるかにコストがかかります。回避できる場合は、フロー制御に使用しないでください。
基本的に、ほとんどの場合、それらを避けることができますが、Java では、状況によっては、フロー制御のためにそれらを使用する方が便利な場合があります。関数型言語では、Either モナドが再び役立ちます。
アサーションを使用する
プログラムの何かが開発者によって真であると想定されている場合は、アサーションを使用して、アサーションが真であることを保証します。グアバの前提条件をご覧ください:
https://code.google.com/p/guava-libraries/wiki/PreconditionsExplained
または、Java ネイティブ アサーションやカスタム コードを使用することもできます。これは、迅速に失敗するのに役立ちます。