67

私はしばらくJavaでコーディングしています。しかし、いつ例外をスローし、いつ例外をキャッチする必要があるのか​​ 理解できないことがあります。私は多くの方法があるプロジェクトに取り組んでいます。階層はこのようなものです -

Method A will call Method B and Method B will call some Method C and Method C will call Method D and Method E.

したがって、現在私がしていることは、すべてのメソッドで例外をスローし、メソッド A でそれをキャッチしてから、エラーとしてログに記録することです。

しかし、これが正しい方法になるかどうかはわかりませんか?または、すべてのメソッドで例外のキャッチを開始する必要があります。それが、この混乱が私の中で始まった理由です-いつ例外をキャッチする必要があるのか​​ 、いつ例外をスローする必要があるのか​​ 。ばかげた質問であることはわかっていますが、どういうわけか、この主要な概念を理解するのに苦労しています。

When to catch the Exception vs When to throw the Exceptions私の概念がこれで明確になるように、誰かが私に詳細な例を教えてもらえますか? 私の場合、例外をスローし続けてから、メソッド A を呼び出すメインで例外をキャッチする必要がありますか?

4

8 に答える 8

7

関数で失敗、つまりエラーが発生した場合は、例外をスローする必要があります。

機能は作業の単位であり、障害はエラーと見なすか、機能への影響に基づいて判断する必要があります。関数f内では、 fがその呼び出し先の事前条件のいずれかを満たすこと、 f自身の事後条件のいずれかを達成すること、または f が維持する責任を共有する不変条件を再確立することを妨げる場合にのみ、失敗はエラーです。

エラーには次の 3 種類があります。

  • 呼び出さなければならない別の関数の前提条件 (パラメーターの制限など) を関数が満たすことを妨げる条件。
  • 関数が独自の事後条件の 1 つを確立するのを妨げる条件 (たとえば、有効な戻り値を生成することは事後条件です)。と
  • 関数が維持する責任がある不変式を再確立することを妨げる状態。これは、特にメンバー関数に適用される特別な種類の事後条件です。すべての非プライベート メンバー関数の重要な事後条件は、クラスの不変条件を再確立する必要があることです。

その他の状態はエラーではなく、エラーとして報告されるべきではありません。

関数がそれ自体で処理できないエラーを検出し、通常の操作または意図された操作のいずれかの形式を続行できない場合は常に、エラーを報告します。

エラーを処理したり、エラーを変換したり、エラー ポリシーで定義された境界を適用したりするための十分な知識がある場所 (メインまたはスレッドのメインラインなど) でエラーを処理します。

出典: C++ コーディング標準: 101 のルール、ガイドライン、ベスト プラクティス

于 2014-07-10T14:12:54.367 に答える
6

1 つまたは 2 つの実稼働環境でベーコンを保存したパターンを共有します。

動機

私の目的は、真夜中に重大度 1 のサポート チケットを解決しようとしている可哀想な男(おそらく私)が、「原因による」エラーの適切な階層を取得し、ID などのデータをすべて煩雑にせずに完了できるようにすることです。コード。

方法

これを実現するために、すべてのチェック済み例外をキャッチし、未チェック例外として再スローします。次に、各アーキテクチャ レイヤーの境界でグローバル キャッチを使用します (通常は抽象化または注入されるため、一度だけ書き込まれます)。これらの時点で、エラー スタックに追加のコンテキストを追加したり、ログに記録して無視するかどうかを決定したり、追加のコンテキストを保持する変数を使用してカスタムのチェック済み例外を発生させたりすることができます。余談ですが、「二重ロギング」の発生を防ぐために、最上位レイヤーでのみエラーをログに記録します (例: cron ジョブ、ajax のスプリング コントローラー)。

throw new RuntimeException(checked,"Could not retrieve contact " + id);

このアプローチでは、データベース関連の例外に対して「スロー」を宣言する必要があるため、GUI またはビジネス層のメソッド シグネチャが乱雑になることはありません。

これが実生活でどのように機能するかの例:

私のコードの仕事は、多くの保険契約を更新するための自動化されたプロセスだとしましょう。このアーキテクチャは、1 つのポリシーの更新を手動でトリガーする GUI をサポートしています。また、これらのポリシーのいずれかの DB で、レーティング エリアの郵便番号が破損しているとします。

達成したいエラーログのタイプの例は次のとおりです。

ログ メッセージ: エラーによる手動介入のポリシー 1234 のフラグ:

スタック トレースから: Error Renewing Policy 1234. Rolling the transaction ... このキャッチは、保存エラーやレターの生成などのエラーもカバーします。

スタック トレースから: 原因: エラー レーティング ポリシー 1234 ...このキャッチは、他の多くのオブジェクトの取得エラーや、NPE などのアルゴリズム エラーを検出します...

スタック トレースから: 原因: レーティング エリアの取得エラー 73932 ...

スタック トレースから: 原因: JPA: フィールド 'postcode' で予期しない null

于 2013-09-08T01:09:02.200 に答える
4

可能な限り低いレベルで例外を処理する必要があります。メソッドが例外を適切に処理できない場合は、それをスローする必要があります。

  • catch リソースに接続するメソッドがある場合 (例: ファイル/ネットワークを開く)
  • 階層の上位のクラスがエラーに関する情報を必要とする場合にスローします
于 2013-09-08T00:36:21.287 に答える
1

他の人が言ったように、原則として、実際に例外を処理できる場合は例外をキャッチする必要があります。そうでない場合は、単にスローします。

たとえば、保存ファイルから接続中のプレーヤーに関する情報を読み取るコードを作成していて、I/O メソッドの 1 つが をスローするIOException場合、その例外をスローし、メソッドを呼び出したコードがそれloadをキャッチする必要があります。例外を処理し、それに応じて処理します (プレーヤーを切断する、クライアントに応答を送信するなど)。メソッドで例外を処理したくない理由はload、メソッドでは意味のある例外を処理できないためです。そのため、呼び出し元が処理できることを期待して例外を呼び出し元に委任します。

于 2013-09-08T01:01:39.317 に答える