38

以前は、次のようなメソッドを含む大量のコードを読んでいました。

public Object doSomething() throws Throwable {
    ...
}

それを行うのは一般的な方法ですか?

長所と短所は何ですか?

throws Trowable例外を取得する「エージェントオレンジ」の方法のように思えました-問題を完了

編集


  1. メソッドで予期される例外を処理する

  2. 予期しない例外をスローする (1 つずつ)

  3. エラーを気にしない

それは行く方法ですか?

4

9 に答える 9

56

投げてはいけませんThrowable。これが理由です。

Throwableは、投げることができるものの階層の最上位であり、とで構成されExceptionsますErrorsErrors定義上、回収不可能な条件から生じるため、メソッド宣言にそれらを含めることは無意味です。それだけExceptionです。

代わりにでメソッドを宣言する必要がありますthrows Exception


範囲が狭いほどthrows良いことに注意してください。

throws Exceptionメソッドが例外を生成しない場合は、メソッドを宣言することは問題ありませんが、代わりに、として宣言されている他のコードを呼び出し、例外throws Exceptionが呼び出しスタックに浸透するようにします。

メソッドが例外を生成している場合は、より狭い範囲を宣言しますthrows IOException, MyProcessingException

于 2012-09-24T11:52:25.917 に答える
10

それは負荷の高い質問です。これは、コードの読みやすさに関するものであるため、例外処理に関するものではありません。

コードサンプルをどこから入手するかによって異なります。専門家は、メソッドを破棄するときに、より具体的にすることを好みます。主な理由は、API を読みやすくするためです。たとえば、メソッドが Throwable をスローする場合、それは基本的に、何かが起こる可能性があり、メソッドがそれを処理したくないことを意味します。しかし、実際には、限られた数のことしか起こり得ません。

  • メソッドで行っている他の呼び出しから生じるチェック済み例外
  • 独自のアサーションに基づいて意図的にスローしているチェック例外
  • 計画していなかった未チェックの例外
  • エラー ( java.lang.Error) は、JVM および環境に対してよりグローバルです

スローする例外を具体的に示すことで、API のユーザーに何に注意する必要があるかを伝えることができます。たとえば、 を使用するInputStreamと、ほとんどのメソッドが少なくともjava.io.IOExceptionをスローすることに気付くでしょう。これにより、何に注意する必要があるかについての有用な情報が得られます。

コーディングするときは、原則として、API をできるだけ表現力豊かに保つようにします。メソッドのパブリック API (つまり、その署名、注釈も推測) を表示するためのコードは基本的に 1 行しかないため、完全に表現力が必要です (戻り値の型、名前、パラメーターだけでなく、スローされた例外も)。

スロー可能オブジェクトをキャッチしてスタック トレースを出力する限り、何かできることがない限り、例外をキャッチするべきではないと思います。代わりに、何らかのクラスがそれをキャッチして何かを行うまで、コール スタックをロールアップさせます。場合によっては、メインクラスまでロールアップすることがあります。これをキャッチして、最後の手段としてスタックトレースを出力する必要があると思います。基本的に、例外に対処できない場合は、コール スタックを上げます。また、例外を黙らせなければならない (つまり、例外をキャッチしても何もしない) 状況に陥ることは非常にまれです。これは通常、問題のトラブルシューティングを行うときに問題を招きます。

これは、一般的な例外処理の誤用に関する楽しくも興味深い記事です。

于 2012-09-24T11:57:25.060 に答える
1

それを行うのは一般的な方法ですか?

JDKではまれです。これは主に、チェックされた例外の処理方法が明確でない場合に使用されます。

長所と短所は何ですか?

長所は、チェックされた例外を気にせずにコードをコンパイルできることです。

短所は、処理する必要のある例外が無視されていることです。

StackTrace()をキャッチして印刷する方が良いのではないでしょうか。

未処理の例外は通常とにかく出力されるため、それらをキャッチしてもあまり役に立ちません。

値を追加できる場合は例外をキャッチし、追加throwsできない場合は句に例外を追加する必要があります。

于 2012-09-24T11:51:16.373 に答える
1

それは本当に議論の余地のある問題です。メソッドがスローする例外が多すぎると、多くのエラー処理コードが生成されます。意図しない場合もあります。

しかし、署名に例外が多すぎるのは好きではないので、すべての例外の親を使用して、完了です!! 効果がないでしょう。

BusinessExceptionできることは、などの例外を分類することです。そのため、その子となる例外が生成される ServiceExceptionというビジネス ルールがあるminimum balance in account can not be less than say 100$場合InsufficientBalanceBusinessException

あなたの方法は次のようになります

public Object doSomething() throws BusinessException {

 if(!hasMinimumbalance())
  { 
    throw new InsufficientBalance(ErrorCode);
  }
}

これにより、クラブ関連の例外がまとめられ、API ユーザーが例外固有のエラーを検出したい場合はいつでもそれを実行できます。それ以外の場合は、一般的なエラー処理が可能です。

ここでの重要な点は、残高が不足していてお金を引き出すことができないことをユーザーに表示する必要がある UI にあります。

人間が読める形式のエラーを表示するには、例外を分離することが本当に必要であると言えます。

于 2012-09-24T12:01:04.497 に答える
1

throws Exceptionエラーがチェックされないため、機能的には と同等です。

Throwable をスローするメソッドを宣言する理由がわかりません。ただし、これは、catch と printStackTrace が優れた代替手段であるという意味ではありません。

通常、投擲可能オブジェクトを適切に処理できる場所でキャッチする必要があります。

予期しないスロー可能オブジェクトをスローするコードは見事に爆発するはずなので、エラーを確認してバグを修正できます。

于 2012-09-24T11:49:43.237 に答える
0

私が考えることができる唯一のユースケースは、単体テストのようなテスト コードです。しかし、Adam の反論は、「もしそうなら、それは良い習慣ではありません。クラス (メソッド) ユーザーに有用な情報を提供しません。」

于 2020-01-17T15:14:24.707 に答える
0

具体的にThrowableについて質問していますか?もしそうなら、それは良い習慣ではありません。クラス(メソッド)ユーザーに役立つ情報を提供しません。

于 2012-09-24T11:50:21.663 に答える
0

一般に、Throwable (または Exception) をスロー (およびキャッチ) することは、キャッチしたい特定の例外を「覆い隠す」ため、悪い習慣です。次に、以下のような醜さに頼る必要があります。

public void myMethod() throws Throwable {
    if (x) {
        throw new MyException1();
    }
    if (y) {
        throw new MyException2();
    }
}

public void callingMethod() {
    try {
        myMethod();
    }
    catch(Throwable t) {
        if (t instanceof MyException1) {
            // handle exception 1
        }
        else if (t instanceof MyException2) {
            // handle exception 2
        }
        else {
            // handle other exceptions
        }
    }
}

これはエラーが発生しやすい (そして CheckStyle によってコード違反としてフラグが立てられる)。次のようなコードを使用することをお勧めします。

public void myMethod() throws MyException1, MyException2 {
    if (x) {
        throw new MyException1();
    }
    if (y) {
        throw new MyException2();
    }
}

public void callingMethod() {
    try {
        myMethod();
    }
    catch(MyException1 e) {
        // handle exception 1
    }
    catch(MyException2 e) {
        // handle exception 2
    }
}

通常、 printStackTrace() を呼び出すだけで例外を処理することはお勧めできません。printStackTrace() はスタックトレースを標準エラーに送信しますが、これはまったく読み取れない可能性があります。より良いオプションは、アプリケーションのログ機能 (log4j など) を使用して例外を報告することです。それでも、ログに記録するだけでは不十分な場合があります。

私の経験則は次のとおりです。

ローカルで例外を処理できる場合は、そうしてください。たとえば、文字列を整数として解析する場合、NumberFormatException をキャッチしてデフォルト値を返すことができます。

prvate int parseAmount(String amountValue) {
    int amount;
    try {
        amount = Integer.parseInt(amountValue);
    }
    catch(NumberFormatException e) {
        // default amount
        amount = 0;
    }
    return amount;
}

例外をローカルで処理できない場合は、スローされている例外の種類を公開する必要があるかどうかを検討してください。この型があいまいな (実装に依存する) 型である場合は、独自の汎用例外型でラップすることをお勧めします。

private Customer getCustomer(int customerId) throws ServiceException {
    try {
        return customerService.getCustomer(customerId);
    }
    catch(CustomerServiceSpaghettiTangledException e) {
        throw new ServiceException("Error calling the customer service", e);
    }
}

ここで、'ServiceException' は、作成した Exception のサブクラスです。Spring は、この目的専用の例外階層も提供します。

例外をラップすることで、実装の詳細を非表示にし、サービス レイヤーをより簡単に使用できるようにします。

メソッドから例外をスローする場合は、コールスタックの「上位」で処理する必要があります。これは、Web アプリケーションの一般的なエラー ページであり、問​​題が発生したことを示し、エラー メッセージまたはコードを提供する可能性があります。場合によっては、より高いレベルのコードが再試行を試みるか、必要な結果を取得するための代替方法を試みることができます。

于 2012-09-24T15:08:02.547 に答える