114

これは実行時例外なので、慎重に使用する必要があるのではないかと心配しています。
標準的な使用例:

void setPercentage(int pct) {
    if( pct < 0 || pct > 100) {
         throw new IllegalArgumentException("bad percent");
     }
}

しかし、それは次の設計を強制するようです:

public void computeScore() throws MyPackageException {
      try {
          setPercentage(userInputPercent);
      }
      catch(IllegalArgumentException exc){
           throw new MyPackageException(exc);
      }
 }

チェック例外に戻すには。

わかりましたが、それで行きましょう。間違った入力をすると、実行時エラーが発生します。まず第一に、実際には一様に実装するのはかなり難しいポリシーです。これは、正反対の変換を行う必要がある可能性があるためです。

public void scanEmail(String emailStr, InputStream mime) {
    try {
        EmailAddress parsedAddress = EmailUtil.parse(emailStr);
    }
    catch(ParseException exc){
        throw new IllegalArgumentException("bad email", exc);
    }
}

さらに悪いこと0 <= pct && pct <= 100に、クライアント コードのチェックは静的に行うことが期待できますが、電子メール アドレスなどのより高度なデータや、さらに悪いことに、データベースに対してチェックする必要があるものについてはそうではありません。検証。

基本的に私が言いたいのは、 の使用に関して意味のある一貫したポリシーが見当たらないということですIllegalArgumentException。使用すべきではないようで、独自のチェック済み例外に固執する必要があります。これをスローするのに適したユースケースは何ですか?

4

6 に答える 6

88

の API ドキュメントIllegalArgumentException:

メソッドに不正または不適切な引数が渡されたことを示すためにスローされます。

それが JDK ライブラリでどのように使用されているかを見ると、次のように言えます。

  • 入力が機能する前に、明らかに不適切な入力について文句を言うのは防御策のように思えます。

  • これは、チェック済み例外をスローするのが煩わしい場合に使用されます (ただし、java.lang.reflect コードに表示されますが、チェック済み例外のスローのばかげたレベルに関する懸念は他では明らかではありません)。

私はIllegalArgumentException、一般的なユーティリティの最後の溝の防御的な引数チェックを行うために使用します(JDKの使用法との一貫性を維持しようとしています)。または、不適切な引数はプログラマーのエラーであると予想される場合、NullPointerException. ビジネスコードに検証を実装するためには使用しません。私は確かに電子メールの例には使用しません。

于 2013-03-04T19:48:30.550 に答える
26

「悪い入力」について話すときは、入力がどこから来ているかを考慮する必要があります。

ユーザーまたは制御していない別の外部システムによって入力された入力は、無効であると予想し、常に検証する必要があります。この場合、チェックされた例外をスローすることはまったく問題ありません。アプリケーションは、ユーザーにエラーメッセージを提供することにより、この例外から「回復」する必要があります。

入力がデータベースやアプリケーションの他の部分などの独自のシステムから発信されている場合は、有効であると信頼できるはずです(入力がそこに到達する前に検証されている必要があります)。この場合、IllegalArgumentExceptionのようなチェックされていない例外をスローすることはまったく問題ありません。これはキャッチされるべきではありません(通常、チェックされていない例外をキャッチすることはできません)。そもそも無効な値がそこに到達したのはプログラマーのエラーです;)修正する必要があります。

于 2013-03-04T20:06:14.547 に答える
17

実行時例外を「控えめに」スローすることは、実際には良いポリシーではありません。Effective Java では、呼び出し元が回復することが合理的に期待できる場合は、チェック済み例外を使用することをお勧めします。(プログラマーのエラーは具体的な例です。特定のケースがプログラマーのエラーを示している場合は、未チェックの例外をスローする必要があります。プログラマーには、ロジックの問題が発生した場所のスタック トレースを取得してもらい、自分で処理しようとしないでください。)

回復の見込みがない場合は、未チェックの例外を自由に使用してください。捕まえても意味がないので、全然いいです。

ただし、この例がコード内にある場合、あなたの例から100%明確ではありません。

于 2013-03-04T18:40:07.197 に答える
6

Oracle公式チュートリアル で指定されているように、次のように述べています。

クライアントが例外から回復することが合理的に期待できる場合は、それをチェック例外にします。クライアントが例外から回復するために何もできない場合は、それを非チェック例外にします。

を使用してデータベースと対話するアプリケーションJDBCがあり、引数をint itemandとして受け取るメソッドがあるとしdouble priceます。対応するアイテムのpriceがデータベース テーブルから読み込まれます。item購入した合計数にprice値を掛けて、結果を返すだけです。私は常に自分の側(アプリケーション側)で、テーブルの価格フィールドの値が負になることは決してないと確信していますが、価格の値がになるとどうなりますか? データベース側に深刻な問題があることを示しています。おそらくオペレーターによる間違った価格入力。これは、そのメソッドを呼び出すアプリケーションの他の部分が予測できず、回復できない種類の問題です。それはBUGあなたのデータベースにあります。だから、そしてIllegalArguementException()この場合、スローする必要がありますthe price can't be negative
私の主張を明確に表明したことを願っています..

于 2013-03-04T19:06:19.187 に答える
6

すべての API は、実行前にパブリック メソッドのすべてのパラメーターの有効性を確認する必要があります。

void setPercentage(int pct, AnObject object) {
    if( pct < 0 || pct > 100) {
        throw new IllegalArgumentException("pct has an invalid value");
    }
    if (object == null) {
        throw new IllegalArgumentException("object is null");
    }
}

それらは、アプリケーションのエラーの 99.9% を表します。これは、不可能な操作を要求しているためです。最終的には、アプリケーションをクラッシュさせるバグです (つまり、回復不可能なエラーです)。

この場合、フェイル ファストのアプローチに従い、アプリケーションの状態を壊さないように、アプリケーションを終了させる必要があります。

于 2015-12-17T11:47:12.703 に答える