5

そもそも例外をスローするのではなく、例外をキャッチして再スローすることの利点について、私は混乱しています。

例えば

private void testMethod() throws Exception
{
    //some bad code here
} 

対:

private void testMethod() throws Exception
{
    try
    {
        //some bad code here
    }
    catch (Exception e)
    {
        throw e;
    }
} //end testMethod()

これは、エラー メッセージのスタック トレースを保持するためですか? 例を設定しようとしましたが、2 つの間で異なる出力は見られませんでした。

助けてくれてありがとう。

4

7 に答える 7

6

2つのコードサンプルの動作に違いはありません。(特に、スタックトレースは、例外がスローされたときではなく、作成されたときに記録されるため、再スローされた例外には元のスタックトレースが残ります)。したがって、通常、人々はより単純なイディオムを使用します。

それは、再スローがその用途を持っていないということではありません。たとえば、FooBarExceptionsを除くすべての例外を処理する場合は、次のように記述できます。

try {
    // bad code 
} catch (FooBarException e) {
    throw e;
} catch (Exception e) {
    e.printStackTrace();
}

または、例外を処理する決定が単にその型をチェックするよりも複雑な場合は、単にそれをキャッチし、処理できないことが判明した場合は再スローできます。

for (int attempts = 0; attemps < 6; attempts++) {
    try {
        return crankyMethod();
    } catch (Exception e) {
        if (fatal(e)) {
            throw e;
        } else {
            // try again
            continue;
        }
    }
}

次の例のように、人々が再スローと言うとき、別の例外をスローすることを意味するものもあることに注意してください。

for (int i = 0; i < array.length; i++) {
    try {
        process(array[i]);
    } catch (Exception e) {
        throw new RuntimeException("Could not process element at index " + i, e);
    }
}

このパターンの利点は、関連する可能性のある追加情報(上記の例では、どのデータを処理できなかったか)で元の例外を装飾することです。元の例外は新しい例外のコンストラクターに渡されるため、そのスタックトレースは失われないことに注意してください。

于 2012-03-08T01:36:41.743 に答える
3

他の人が言ったように、あなたの例では違いはなく、2 番目の形式は避ける必要があります。

場合によってはそれが意味を成す唯一の場所は、いくつかの例外をキャッチする必要があり、他の例外を上向きにスローする必要がある場合です。Java の例外処理構文には制限があるため、次のようにすることがあります。

try {
   somePieceOfCode();
} catch( RuntimeException e ) {
   throw e;
} catch( Exception e ) {
   handleException(e);
}

somePieceOfCodeこれは、共通の基本クラス ( 以外Exception) を持たないが、同じ方法で処理する必要がある多数の異なるチェック済み例外を がスローする場合に行われることがあります。Exceptionのようなものもキャッチするため、単にキャッチしたくないNullPointerException場合があり、それらの例外をそのままバブルアップすることを好む場合があります。

このコードは、すべてRuntimeExceptionsを上方にバブルさせますが、他のすべての例外を処理します。

このイディオムは少し変わっていて、誰もが好きというわけではありませんが、どこかで見られるかもしれません。

于 2012-03-08T01:16:19.160 に答える
1

このアプローチを使用すると、例外を変更できます。たとえば、より具体的なメッセージを与えることができます。

とはいえ、通常、この手法は使用しないでください。

  • コードをクラスター化して追加の利点はありません (通常の状況では)
  • 実行が遅くなる可能性があるため、実際に必要な場合にのみ try-catch ブロックを使用する必要があります
于 2012-03-08T01:10:41.690 に答える
1

例外をキャッチして再スローする標準的な理由は次のとおりです。

  1. インシデントと例外をログに記録します。
  2. 例外によるクリーンアップを行うため (ただし、finally ブロックで行う方がよい場合が多い)。
  3. より適切な例外で例外をラップするには (つまり、processAccount() メソッドが DbException の代わりに AccountException (またはそのようなもの) をスローする方がおそらく適切です)。
于 2012-03-08T01:11:39.060 に答える
0

キャッチしてから再スローする主な利点の1つは、例外を別のドメイン固有の例外でラップすることです。これにより、呼び出し元のコードは実装固有の問題について心配する必要がなく、ライブラリ固有の例外をキャッチできます。

あなたが与えた例には本当の利点はありませんが、そのような利点の良い例は他のライブラリで見ることができます-例としてHibernateを見ることができます。

Hibernateは汎用SQLExceptionをキャッチし、オブジェクトを調べて例外の実際の原因を特定してから、問題が最初に何であったかをより説明するHibernate固有の例外でラップします。

ただし、例外をキャッチして同じ例外をスローするだけの場合は、最初に例外をログに記録できるようにするために、それを実行する可能性が最も高くなります(ただし、これが必ずしも最適な方法であるとは限りません)。

于 2012-03-08T01:18:37.123 に答える
0

違いはありません。再スローする前に何かをしたい場合を除きます(例外)。

于 2012-03-08T00:59:12.343 に答える
0

大きな違いはないと思いますが、価値があるので、最初のものを好みます。

何らかの対処ができる場合、またはクラスが境界であり、それを超えて例外が伝播されない場合 (たとえば、すべての例外をキャッチし、ユーザーをわかりやすいエラー ページにルーティングする Web コントローラー) でない限り、例外をキャッチしないでください。

単にキャッチして再スローするだけでは、キーストロークが無駄になります。情報を追加せず、建設的なことは何もしません。

1 つの例外は、チェック済みの例外をキャッチし、それを未チェックの例外としてラップすることです。それ以外の場合は、2 番目のイディオムを避けてください。

于 2012-03-08T00:59:40.633 に答える