5

この質問にはすでに答えがあります。

いくつかの従来のコードでは、私はこれを見ています。オーバーブロードな例外がキャッチされ、そして再び投げられています。これは良い習慣ですか?するthrow e;同じ例外を再スローするか、新しい例外を作成しますか。

catch (Exception e) {
        StringBuilder sb = new StringBuilder(
                            "Oops. Something went wrong with id: ");
        sb.append(id);
        sb.append(". Exception is: ");
        sb.append(e.toString());
        System.out.println(sb.toString());
        throw e;
}


  • 例外を渡し続けたい場合は、キャッチして再スローしても問題ありません。コードがそれをキャッチし、それをログに記録し、そして再びそれをスローするのであれば、それは奇妙に思えます。 - Andrew

5 답변


2

throw e同じ例外を再スローしています。少なくとも元のスタックトレースを保存します。何が起こったのかについての情報を記録した標準出力にメッセージを書いてから、元の例外を途中で進行させるだけです。

これは良い習慣ではありません。例外を中央の場所に記録し、それらのスタックトレースを記録するだけで十分なはずです。より多くの情報を追加する必要がある場合(例のように、IDをログに記録する場合)、元の例外を原因として新しい例外にネストしてから、新しい例外をスローすることをお勧めします。これはおそらく集中ログがない状況や例外がどこかで食いつく傾向がある状況で起こると思います。


  • どこにもログが記録されているとは思われません。発生した例外が確実に表示されるようにして、例外をログに記録するように中央の場所で対策を講じることで、クライアントに希望どおりに適切に処理するように依頼するだけです。 - Prateek
  • @Prateek:ロギングとは、標準出力への書き込みを意味します(非常に粗雑ですが、一種のロギングです)。今すぐ再説明しました。 - Nathan Hughes
  • わかりましたが、それでもrethrowing異なるクライアントはこれらの例外を異なる方法で処理しようと試みるかもしれないので、例外は実際には良いかもしれません。同意しませんか。 - Prateek
  • @Prateek:中にネストされている古い例外で新しい例外を投げるのが私の望ましい方法でしょう。そのようにして、新しい例外はより多くの情報を追加することができ、例外のタイプは異なる場合があります。 - Nathan Hughes
  • ええ、それは私が追いかけるものですが、これも悪くはありません:) - Prateek

1

これは通常悪い習慣です。catch(Exception e)(時々呼ばれるポケモン例外処理ときのためにあなたはそれらすべてをキャッチしなければならない)キャッチすべての単一の例外そのような例外処理は、以下の理由であまり役に立ちません。

  • 実行時例外もキャッチします。
  • スローされた例外の種類に関する情報を失います。
  • あなたは反応することができない特定例外です。

あなたのメソッドシグネチャは今public void whatever() throws Exceptionこれはめったに役に立ちません。これでチェーンの上位にあるものすべてが、どのような例外をスローしたのかわからなくなります。彼らはしなければならないでしょうinstanceof特定の例外をすべてキャッチするという目的を完全に無効にします。

あなたの2番目の例外に関する限り、throw e;同じ例外オブジェクトをスローします。例外をラップしたい場合は、新しい例外を作成できます。つまり、次のようにします。throw new MyCustomException(e);。メソッドシグネチャも変更する必要があります。

それ以上連鎖がない場合は、これはそれほど悪くはないと思います(それでもまだ素晴らしいとは言えません)。スローされたすべての例外をログに記録しようとしているメソッドのように見えます。ただし、これを行うにはもっと良い方法があります。


1

私が一番思うのは、それが2層の保護を得ようとしていることでしょう。エラーメッセージが表示されていることを確認し、クライアントに例外の処理方法を要求します。catch句は例外から回復するために何もしていません。

私はそれを良い/悪い習慣とは考えません。あなたの要件に応じて、あなたはあなたのAPIを使用している100の異なるクライアントがあり、それらのそれぞれが異なる方法から回復する異なる方法を持っているかもしれないようにどちらかの方法で進むと考えることができますexception。何が問題なのかを表示することで、クライアントがどのように処理するかを決定する層のすぐ下にデフォルトのアクション層を追加します。exception

さて、あなたの質問に戻りましょう。おもうthrow e同じ例外オブジェクトをスローします。例外としてobjectsJavaではあなたが作成する必要がありますnew exception objectあなたができる前にthrowそれは私があなたのコードで起こっているのを見ることができないそれです。


  • あなたはあなたがJavaで新しい例外を投げなければならないというあなたの主張について確実ですか? - pamphlet
  • @pamphlet重要なのは、カスタマイズした例外をスローしなければならないときに、例外クラス(またはそれを拡張したもの)のオブジェクトを作成しなければならない場合です。throwそれ。上記のコードでは、例外オブジェクトcreate otherはありません。e - Prateek

0

throw e同じ例外が発生します。これを行う理由があったかもしれませんが、しない理由もあります。サンプルコードでは、メッセージがに送信されます。System.outしかし、後でスタックトレースが表示された場合System.errそれは同期されません、そして実際には2つはあなたのコンソールに織り込まれるかもしれません。

より良い方法は次のとおりです。

catch (Exception e) {
    StringBuilder sb = new StringBuilder(
                        "Oops. Something went wrong with id: ");
    sb.append(id);
    sb.append(". Exception is: ");
    sb.append(e.toString());
    throw new Exception(sb.toString(), e); // The original exception is an argument
}

これは新しいを作成しますException修正されたメッセージで、そしてオリジナルを追加するExceptionデバッグに役立つスタックトレースへ。


  • 他の選択肢は適切なロギングメカニズムを使用することです。 - pamphlet

0

それは良い習慣です。私はいつもに変換を使用すると思いますRuntimeException試作中です。その後、必要があれば、これをより良い例外処理に変えることができます。この私の目的のためにグアバには以下のユーティリティクラスがあります。使い捨てこれは例外伝播を引き起こします。

しかしあなたの場合は例外はランタイム例外に変換なぜなら、一般を投げるメソッドを宣言するからです。Exceptionスローするメソッドとまったく同じです。RuntimeExceptionコーリングパーティのため。最初のケースではそれすべてをキャッチ「後者ではそれ」何でもキャッチ'。実際のアプリケーションでは、これら2つの違いはまだ経験していません。だから私は好きですRuntimeException入力が少なくて済むのでs。

キャッチException

  • チェックされた例外(IO例外、セキュリティエラー、同時実行性など)
  • 実行時例外(何でも、予測できないゴミ、下記参照)
  • すべて - これらはすべてのエラーの99%です(Errorしかし左)

キャッチRuntimeException

  • nullポインタ例外、範囲外インデックス、アクセス例外、+ラップして例外をRuntimeException- これはまたたくさん

私が大事にしているのは、Exceptionあなたは本当にこれらすべてのケースを扱うことはできません。それで、あなたがそれをにラップした場合、それは発呼者のための少ないタイピングを除いて違いを生じません。RuntimeException


  • 将軍を投げるException投げることと同じではありませんRuntimeException。前者がチェックされているので、メソッドシグネチャに記載する必要があります。のサブクラスである例外ExceptionしかしではないのサブクラスRuntimeExceptionチェック例外です。 - Vivin Paliath
  • ええ、それは正しいです。私が言っているのは、それが発呼側にとって何の問題もないということです。キャッチ全般Exceptionすべてを捕捉することを意味します。キャッチRuntimeException何かをキャッチすることを意味します。 2つのケースで実際の違いが見られることはまだありません。 - Andrey Chaschev
  • それ意志発呼側に違いを生む。メソッドがスローされている場合Exceptionその場合、呼び出し元はそれを処理するか再スローする必要がありますが、メソッドがスローされている場合はどちらも実行する必要はありません。RuntimeException。キャッチもRuntimeException「何かを捕まえる」という意味ではありません。それのみのサブクラスである例外をキャッチします。RuntimeException(そしてRuntimeException自体);確認済みの例外が検出されませんでした。 - Vivin Paliath
  • うん、論理的な違いがあります。まだ使用されていないようです。ほとんどの場合、将軍を投げるExceptionJavaでは悪い習慣であるため、実際の例を考えるのは本当に難しいでしょう。を伝播するRuntimeExceptionしかし、アンチパターンではありえないし、それは良い習慣になり得る。 - Andrey Chaschev

リンクされた質問


関連する質問

最近の質問