チェックされた例外とチェックされていない例外を選択するタイミング


213

Java(または例外がチェックされている他の言語)では、独自の例外クラスを作成するときに、クラスをチェックするかチェックしないかをどのように決定しますか?

私の本能は、チェックされた例外は呼び出し側が何らかの生産的な方法で回復できる可能性がある場合に呼び出され、チェックされていない例外は回復不可能な場合により多くなるが、私は他の人の考えに興味があると言うことです。


11
Barry Ruzekはチェック済みまたは未チェックの例外の選択に関する優れたガイドを作成しました
sigget 2009

回答:


241

チェック例外は、いつ使用すべきかを理解している限り、すばらしいものです。JavaコアAPIは、SQLException(および場合によってはIOException)に関するこれらのルールに準拠していないため、非常にひどいです。

チェックされた例外は、予測可能であるが回避できないエラーから回復するために使用する必要があります。

未チェックの例外は他のすべてに使用する必要があります。

ほとんどの人がこれが何を意味するのか誤解しているので、私はあなたのためにこれを分解します。

  1. 予測可能ですが、防止できません:呼び出し元は、入力パラメーターを検証するためにすべての操作を実行しましたが、制御外の条件が原因で操作が失敗しました。たとえば、ファイルを読み取ろうとしたが、ファイルが存在するかどうかを確認してから読み取り操作が始まるまでの間に誰かがファイルを削除したとします。チェック例外を宣言することで、この失敗を予測するように呼び出し元に伝えます。
  2. 回復するのが合理的回復できない例外を予想するように発信者に伝える意味はありません。ユーザーが存在しないファイルから読み取ろうとした場合、呼び出し元は新しいファイル名を要求することができます。一方、プログラミングのバグ(無効なメソッド引数またはバグの多いメソッド実装)が原因でメソッドが失敗した場合、アプリケーションは実行中の問題を修正するためにできることは何もありません。最善の方法は、問題をログに記録し、後で開発者が修正するのを待つことです。

スローしている例外が上記の条件をすべて満たしていない限り、チェックされていない例外を使用する必要があります。

すべてのレベルで再評価:チェックされた例外をキャッチするメソッドが、エラーを処理するのに適していない場合があります。その場合は、自分の発信者にとって何が妥当かを検討してください。例外が予測可能で、防止できず、回復するのに合理的である場合は、チェックされた例外を自分でスローする必要があります。そうでない場合は、チェックされていない例外で例外をラップする必要があります。このルールに従うと、どのレイヤーにいるかによって、チェックされた例外をチェックされていない例外に、またはその逆に変換します。

チェックされた例外とチェックされていない例外の両方について、適切な抽象化レベルを使用します。たとえば、2つの異なる実装(データベースとファイルシステム)を備えたコードリポジトリでは、SQLExceptionまたはをスローすることで実装固有の詳細を公開しないようにする必要がありますIOException。代わりに、すべての実装にまたがる抽象化で例外をラップする必要があります(例:)RepositoryException


2
「ファイルを読み取ろうとしたが、ファイルが存在するかどうかを確認してから読み取り操作が始まるまでの間に誰かがファイルを削除した。」=>これはどのように「期待」されていますか?私にはそれは次のように聞こえます:予期せず、防止可能です。
Koray Tugay

9
@KorayTugay Expectedは、シナリオが典型的であるという意味ではありません。これは、このエラーが事前に発生することを予測できることを意味します(事前に予測できないプログラミングエラーと比較して)。Unpreventableとは、ファイルが存在するかどうかを確認してから読み取り操作が始まるまでの間に、ユーザーまたは他のアプリケーションがファイルを削除できないようにするためにプログラマができることは何もないということです。
ギリ

したがって、メソッド内のデータベース関連の問題は、チェック例外をスローする必要がありますか?
ivanjermakov

59

Java学習者から:

例外が発生した場合は、例外をキャッチして処理するか、メソッドがその例外をスローすることを宣言して処理できないことをコンパイラに通知する必要があります。そうすると、メソッドを使用するコードはその例外を処理する必要があります(例外でも)処理できない場合は例外をスローすることを宣言することもできます)。

コンパイラーは、2つの処理(キャッチまたは宣言)のいずれかを実行したことを確認します。したがって、これらはチェック済み例外と呼ばれます。ただし、エラーおよびランタイム例外はコンパイラーによってチェックされません(キャッチまたは宣言することを選択できても、必須ではありません)。したがって、これら2つはチェックされない例外と呼ばれます。

エラーは、システムのクラッシュなど、アプリケーションの外部で発生する状態を表すために使用されます。ランタイム例外は通常、アプリケーションロジックの障害によって発生します。このような状況では何もできません。実行時例外が発生した場合は、プログラムコードを書き直す必要があります。したがって、これらはコンパイラーによってチェックされません。これらのランタイム例外は、開発およびテスト期間中に明らかになります。次に、これらのエラーを削除するためにコードをリファクタリングする必要があります。


13
それが正統派の見方です。しかし、それについては多くの論争があります。
artbristol 2012年

49

私が使用するルールは、チェックされていない例外を使用しないことです。(またはそれを回避する方法がない場合)

反対の場合には非常に強力なケースがあります。チェックされた例外を使用しないでください。私はこの議論に賛成するのをためらいますが、チェックされた例外を導入することは、後から見た誤った決定であるという幅広いコンセンサスがあるようです。メッセンジャーを撃って、それらの 議論を参照しないでください


3
IMHO、チェックされた例外は、メソッドが特定のコードブロックで呼び出されたメソッドが特定の例外(またはまったく)をスローすることを期待していないことを宣言する簡単な方法があり、このような期待に反してスローされる例外は、他の例外タイプにラップされて再スローされる必要があります。コードがチェック例外に対処する準備ができていない時間の90%は、そのようなラップアンドスローがそれを処理する最良の方法だと思いますが、言語サポートがないため、めったに行われません。
スーパーキャット2013年

@supercat基本的にはそれだけです。私は厳密な型チェックの熱心なファンであり、チェックされた例外はその論理的な拡張です。概念的には非常に気に入っていますが、チェック例外は完全に破棄しました。
Konrad Rudolph

1
私が説明したメカニズムが解決する例外の設計である1つの不満は、ファイルの終わりを超えて読み取るときにfooスローbarExceptionするようにドキュメント化されており、それを予期していないにもかかわらずfooスローするメソッドを呼び出す場合、呼び出すコードは、ファイルの終わりに到達したと見なし、予期しないことが起こったという手がかりはありません。私はその状況を、チェックされた例外が最も役立つはずであると考えていますが、コンパイラが未処理のチェックされた例外を許可する唯一のケースでもあります。barExceptionfoofoo
スーパーキャット2013年

@supercat:最初のコメントでコードがやりたいことを簡単に行う方法はすでにあります。tryブロックでコードをラップし、Exceptionをキャッチして、ExceptionをRuntimeExceptionでラップして再スローします。
Warren Dew

1
@KonradRudolph supercatは「特定のコードブロック」を参照しました。ブロックを定義する必要がある場合、宣言型構文は膨張を大幅に削減しません。関数全体で宣言的であると考えている場合、人々は実際にキャッチされたチェック済み例外を実際に見るのではなく宣言に固執し、他に他の方法がないことを確認するため、悪いプログラミングを奨励します。それらを処理します。
Warren Dew

46

多くの層を持つ十分な規模のシステムでは、チェックされた例外は役に立たない。とにかく、例外の処理方法を処理するためのアーキテクチャレベルの戦略が必要である(障害バリアを使用)。

チェックされた例外を除いて、エラー処理ステートはマイクロマネージドであり、大規模なシステムでは耐えられません。

ほとんどの場合、APIの呼び出し元がどの層にあるのかわからないため、エラーが「回復可能」かどうかはわかりません。

整数の文字列表現をIntに変換するStringToInt APIを作成するとします。APIが「foo」文字列で呼び出された場合、チェック例外をスローする必要がありますか?回復可能ですか?彼のレイヤーでは、私のStringToInt APIの呼び出し元が既に入力を検証している可能性があるため、私にはわかりません。この例外がスローされた場合、それはバグまたはデータの破損であり、このレイヤーでは回復できません。

この場合、APIの呼び出し元は例外をキャッチしたくありません。彼は例外を「バブルアップ」させたいだけです。チェックされた例外を選択した場合、この呼び出し元は、人為的に例外を再スローするためだけに、多くの役に立たないcatchブロックを持っています。

回復可能なものは、ほとんどの場合、APIの作成者ではなく、APIの呼び出し元に依存します。チェックされていない例外のみが例外をキャッチするか無視するかを選択できるため、APIはチェックされた例外を使用しないでください。



15
@alexsmailインターネットは私を驚かせることに失敗することはありません、実際にはそれは私のブログです:)
ステファン

30

あなたは正しいです。

チェックされていない例外を使用して、システムをすばやく失敗させることができます。これは良いことです。メソッドが適切に機能するためには、メソッドが何を期待しているのかを明確に示す必要があります。この方法では、入力を1回だけ検証できます。

例えば:

/**
 * @params operation - The operation to execute.
 * @throws IllegalArgumentException if the operation is "exit"
 */
 public final void execute( String operation ) {
     if( "exit".equals(operation)){
          throw new IllegalArgumentException("I told you not to...");
     }
     this.operation = operation; 
     .....  
 }
 private void secretCode(){
      // we perform the operation.
      // at this point the opreation was validated already.
      // so we don't worry that operation is "exit"
      .....  
 }

ほんの一例です。重要なのは、システムが速く故障した場合、どこで、なぜ故障したのかがわかるでしょう。次のようなスタックトレースが表示されます。

 IllegalArgumentException: I told you not to use "exit" 
 at some.package.AClass.execute(Aclass.java:5)
 at otherPackage.Otherlass.delegateTheWork(OtherClass.java:4569)
 ar ......

そして、あなたは何が起こったかを知るでしょう。「delegateTheWork」メソッド(4569行目)のOtherClassは、「exit」値を使用してクラスを呼び出しました。

それ以外の場合は、コード全体に検証を散布する必要があり、エラーが発生しやすくなります。さらに、何が問題であったかを追跡することが困難な場合があり、イライラするデバッグに何時間もかかることが予想されます。

NullPointerExceptionsでも同じことが起こります。15のメソッドを含む700行のクラスがあり、30の属性を使用し、どれもnullにすることができない場合、それらのメソッドごとにnullが可能かどうかを検証する代わりに、これらの属性をすべて読み取り専用にして、コンストラクターで検証するか、ファクトリーメソッド。

 public static MyClass createInstane( Object data1, Object data2 /* etc */ ){ 
      if( data1 == null ){ throw NullPointerException( "data1 cannot be null"); }

  }


  // the rest of the methods don't validate data1 anymore.
  public void method1(){ // don't worry, nothing is null 
      ....
  }
  public void method2(){ // don't worry, nothing is null 
      ....
  }
  public void method3(){ // don't worry, nothing is null 
      ....
  }

チェックされた例外プログラマー(あなたまたはあなたの同僚)がすべてを正しく行い、入力を検証し、テストを実行し、すべてのコードは完璧ですが、コードがダウンしている可能性のあるサードパーティのWebサービス(またはファイル)に接続している場合に役立ちます。使用していたものが別の外部プロセスによって削除されたなど)。接続が試行される前にWebサービスを検証することもできますが、データ転送中に問題が発生しました。

そのシナリオでは、あなたや同僚がそれを助けるためにできることは何もありません。しかし、それでも、何かをしなければならず、アプリケーションがユーザーの目に死んで消えるだけではいけません。あなたはそのためにチェックされた例外を使用し、例外を処理します、それが起こったときに何ができますか?ほとんどの場合、エラーをログに記録し、おそらく作業(アプリの作業)を保存してユーザーにメッセージを表示します。(サイトblablaがダウンしています。後で再試行してください。)

チェックされた例外が過剰に使用された場合(すべてのメソッドシグネチャに "throw Exception"を追加することにより)、誰もがその例外を無視するため(一般的すぎるため)、コードの品質は深刻になります。妥協。

チェックされていない例外を使いすぎると、同様のことが起こります。そのコードのユーザーは、何かがうまくいかないかもしれないことを知りません。多くのtry {...} catch(Throwable t)が表示されます。


2
よく言った!+1。この呼び出し元(チェックされていない)/呼び出し先(チェックされている)の区別が明確ではないことに常に驚かされます...
VonC '27

19

これが私の「最終的な経験則」です。
私が使う:

  • 私のメソッドのコード内でチェックされていない例外、呼び出し元によるエラー明示的かつ完全なドキュメントを含む)
  • 私のコードを使用したい人に明示する必要がある呼び出し先による失敗の例外確認しました

前の回答と比較すると、これは、どちらか一方(または両方)の種類の例外を使用するための明確な根拠(これに同意または反対することができます)です。


これらの両方の例外について、非常に一般的なチェックされていない例外(NullPointerExceptionなど)を除いて、アプリケーションに対して独自のチェックされていないチェックされた例外を作成します(ここで言及されているように、良い方法です)。

したがって、たとえば、以下のこの特定の関数の目標は、オブジェクトを作成する(または既に存在する場合は取得する)ことです。
つまり、

  • 作成/取得するオブジェクトのコンテナが存在する必要があります(CALLERの責任
    =>未チェックの例外、およびこの呼び出された関数のjavadocコメントをクリア)
  • 他のパラメーターはnullにできません
    (CALLERにそれを置くためのコーダーの選択:コーダーはnullパラメーターをチェックしませんが、コーダーはそれを行います)
  • 結果をNULLにすることはできません
    (呼び出し先のコードの責任と選択、呼び出し元にとって非常に重要な選択
    =>チェック例外)すべての呼び出し元は、オブジェクトを作成/発見できない場合に決定を行わなければならないため、決定はコンパイル時に実行する必要があります。この可能性に対処する必要がない限り、この関数を使用することはできません。つまり、このチェックされた例外を意味します)。

例:


/**
 * Build a folder. <br />
 * Folder located under a Parent Folder (either RootFolder or an existing Folder)
 * @param aFolderName name of folder
 * @param aPVob project vob containing folder (MUST NOT BE NULL)
 * @param aParent parent folder containing folder 
 *        (MUST NOT BE NULL, MUST BE IN THE SAME PVOB than aPvob)
 * @param aComment comment for folder (MUST NOT BE NULL)
 * @return a new folder or an existing one
 * @throws CCException if any problems occurs during folder creation
 * @throws AssertionFailedException if aParent is not in the same PVob
 * @throws NullPointerException if aPVob or aParent or aComment is null
 */
static public Folder makeOrGetFolder(final String aFoldername, final Folder aParent,
    final IPVob aPVob, final Comment aComment) throws CCException {
    Folder aFolderRes = null;
    if (aPVob.equals(aParent.getPVob() == false) { 
       // UNCHECKED EXCEPTION because the caller failed to live up
       // to the documented entry criteria for this function
       Assert.isLegal(false, "parent Folder must be in the same PVob than " + aPVob); }

    final String ctcmd = "mkfolder " + aComment.getCommentOption() + 
        " -in " + getPNameFromRepoObject(aParent) + " " + aPVob.getFullName(aFolderName);

    final Status st = getCleartool().executeCmd(ctcmd);

    if (st.status || StringUtils.strictContains(st.message,"already exists.")) {
        aFolderRes = Folder.getFolder(aFolderName, aPVob);
    }
    else {
        // CHECKED EXCEPTION because the callee failed to respect his contract
        throw new CCException.Error("Unable to make/get folder '" + aFolderName + "'");
    }
    return aFolderRes;
}

19

それは例外から回復する能力の問題だけではありません。私の意見では、最も重要なのは、呼び出し元が例外をキャッチすることに関心があるかどうかです。

他の場所で使用するライブラリ、またはアプリケーションの下位層を作成する場合は、呼び出し元が例外をキャッチ(認識)することに関心があるかどうかを自問してください。そうでない場合は、チェックされていない例外を使用して、不必要に彼に負担をかけないようにします。

これは、多くのフレームワークで使用されている哲学です。特に、SpringとHibernateが頭に浮かびます。Javaではチェック済み例外が過剰に使用されているため、既知のチェック済み例外を未チェックの例外に変換します。私が考えることができる1つの例は、json.orgからのJSONExceptionです。これは、チェックされた例外であり、ほとんど煩わしいものです。チェックを外す必要がありますが、開発者は単純にそれを考えていません。

ちなみに、ほとんどの場合、呼び出し側の例外への関心は、例外からの回復機能に直接関係していますが、常にそうであるとは限りません。


13

これは、チェック済み/未チェックのジレンマに対する非常に簡単な解決策です。

ルール1:コードが実行される前に、チェックされない例外をテスト可能な条件と考えます。例えば…

x.doSomething(); // the code throws a NullPointerException

ここで、xはnullです...…コードには次のものが含まれている可能性があります…

if (x==null)
{
    //do something below to make sure when x.doSomething() is executed, it won’t throw a NullPointerException.
    x = new X();
}
x.doSomething();

ルール2:チェック例外は、コードの実行中に発生する可能性があるテスト不可能な条件と考えてください。

Socket s = new Socket(“google.com”, 80);
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();

…上の例では、DNSサーバーがダウンしているため、URL(google.com)が使用できない場合があります。DNSサーバーが機能していて、「google.com」の名前をIPアドレスに解決した瞬間でも、google.comに接続すると、いつでもネットワークがダウンする可能性があります。ストリームの読み取りと書き込みを行う前に、常にネットワークをテストすることはできません。

問題があるかどうかを知る前に、コードを実行する必要がある場合があります。Checked Exceptionを介してこれらの状況を処理するように開発者にコードを書くよう強制することにより、私はこの概念を発明したJavaの作成者に帽子をかぶらなければなりません。

一般に、JavaのほとんどすべてのAPIは、上記の2つのルールに従います。ファイルに書き込もうとすると、書き込みが完了する前にディスクがいっぱいになる可能性があります。他のプロセスが原因でディスクがいっぱいになった可能性があります。この状況をテストする方法はありません。いつでもハードウェアの使用が失敗する可能性があるハードウェアとやり取りする人にとって、チェック例外はこの問題のエレガントな解決策のようです。

これには灰色の領域があります。多くのテストが必要な場合(多くの&&と||を含むifステートメントに心を吹き飛ばします)、スローされる例外はCheckedExceptionになります。プログラミングエラーです。テストが10をはるかに下回る場合(たとえば、 'if(x == null)')、プログラマエラーはUncheckedExceptionになります。

言語通訳者を扱うとき、物事は面白くなります。上記のルールに従って、構文エラーはチェック済みまたは未チェックの例外と見なす必要がありますか?言語の構文が実行される前にテストできる場合、それはUncheckedExceptionであるべきだと私は主張します。言語をテストできない場合—アセンブリコードがパーソナルコンピューターで実行される方法と同様に、構文エラーはチェック例外でなければなりません。

上記の2つのルールにより、選択対象の懸念の90%がおそらく除去されます。ルールを要約するには、次のパターンに従います... 1)実行するコードを実行前にテストして、正しく実行するためにテストでき、例外が発生した場合(別名プログラマーエラー)、例外はUncheckedException(RuntimeExceptionのサブクラス)になります。 )。2)実行するコードが正しく実行されるために実行前にテストできない場合、例外はチェック済み例外(Exceptionのサブクラス)である必要があります。


9

これをチェック済みまたは未チェックの例外と呼ぶことができます。ただし、どちらのタイプの例外もプログラマーがキャッチできるため、最善の答えは、すべての例外をチェックされていないものとして記述、それらを文書化することです。これにより、APIを使用する開発者は、その例外をキャッチして何かを実行するかどうかを選択できます。チェックされた例外は、すべての人の時間を完全に浪費するものであり、コードを見ると衝撃的な悪夢になります。適切な単体テストを行うと、キャッチして何かをしなければならない可能性のある例外が表示されます。


1
+1単体テストは、チェックされた例外が解決することを目的とする問題を解決するためのより良い方法であるかもしれないことに言及してください。
キース・ピンソン、

ユニットテストの場合は+1。Checked / Uncheked例外を使用しても、コードの品質にはほとんど影響しません。したがって、チェックされた例外を使用するとコード品質が向上するという主張は、完全な偽の引数です!
user1697575 2013年

7

チェック例外: クライアントが例外から回復でき、続行したい場合は、チェック例外を使用します。

未チェックの例外:例外の 後でクライアントが何もできない場合は、未チェックの例外を発生させます。

例:メソッドA()でA()からの出力に基づいて算術演算を行うことが予想される場合は、別の演算を行う必要があります。実行時に予期しないメソッドA()からの出力がnullの場合、実行時例外であるNullポインタ例外をスローすることが期待されます。

こちらを参照


2

特にAPIを設計する場合は、原則として未チェックの例外を優先することに同意します。呼び出し側は常に、文書化された未チェックの例外をキャッチすることを選択できます。不必要に発信者を強制するだけではありません。

実装の詳細として、チェック例外は下位レベルで役立ちます。指定されたエラー「戻りコード」を管理する必要があるよりも、制御メカニズムのフローが優れているように見えることがよくあります。低レベルのコード変更のアイデアの影響を確認するのにも役立つ場合があります...チェックされた例外を下流で宣言し、誰が調整する必要があるかを確認します。この最後の点は、多くのジェネリックがある場合には当てはまりません 。catch(Exception e) または例外スローしますが、通常はとにかくあまり考えられていません。


2

ここでは、長年の開発経験の後に私が持っている私の意見を共有したいと思います。

  1. 例外を確認しました。これは、ビジネスユースケースまたはコールフローの一部です。これは、私たちが期待する、または期待しないアプリケーションロジックの一部です。たとえば、接続が拒否された、条件が満たされていないなどです。これを処理し、対応するメッセージをユーザーに表示して、何が起こったか、次に何をすべきかを指示します(後で再試行するなど)。私は通常、これを後処理例外または「ユーザー」例外と呼びます。

  2. 未チェックの例外。これはプログラミング例外の一部であり、ソフトウェアコードプログラミングのいくつかの間違い(バグ、欠陥)であり、ドキュメントに従ってプログラマーがAPIを使用する方法を反映しています。外部のlib / frameworkドキュメントが、NPEまたはIllegalArgumentExceptionがスローされるため、ある範囲のデータとnull以外のデータを取得すると想定している場合、プログラマーはそれを予期し、ドキュメントに従ってAPIを正しく使用する必要があります。それ以外の場合は、例外がスローされます。私は通常、これを前処理例外または「検証」例外と呼びます。

対象者ごと。ここで、例外が設計された対象読者または人々のグループについて話しましょう(私の意見に従って):

  1. 例外を確認しました。対象読者はユーザー/クライアントです。
  2. 未チェックの例外。対象読者は開発者です。言い換えれば、チェックされていない例外は開発者のみを対象としています。

アプリケーション開発ライフサイクルフェーズごと。

  1. チェック例外は、アプリケーションが例外的なケースを処理する通常の予期されるメカニズムとして、本番ライフサイクル全体で存在するように設計されています。
  2. 未チェックの例外は、アプリケーションの開発/テストのライフサイクル中にのみ存在するように設計されています。それらはすべて、その期間中に修正する必要があり、アプリケーションがすでに本稼働で実行されている場合はスローしないでください。

フレームワークが通常チェックされない例外(Springなど)を使用する理由は、フレームワークがアプリケーションのビジネスロジックを決定できないためです。これは、開発者が独自のロジックをキャッチして設計することです。


2

プログラマーのエラーかどうかに基づいて、これら2つのタイプの例外を区別する必要があります。

  • エラーがプログラマエラーの場合は、チェックされていない例外である必要があります 例:SQLException / IOException / NullPointerException。これらの例外はプログラミングエラーです。これらはプログラマーが処理する必要があります。JDBC APIではSQLExceptionはチェック例外ですが、Spring JDBCTemplateではチェックされない例外です。Springを使用する場合、プログラマはSqlExceptionについて心配しません。
  • エラーがプログラマーエラーではなく、理由が外部からのものである場合、それはチェック済み例外である必要があります。例:ファイルが削除された場合、またはファイルのアクセス権が他のユーザーによって変更された場合は、回復する必要があります。

FileNotFoundExceptionは、微妙な違いを理解する良い例です。FileNotFoundExceptionは、ファイルが見つからない場合にスローされます。この例外には2つの理由があります。ファイルパスが開発者によって定義されているか、GUIを介してエンドユーザーから取得されている場合、チェックされない例外になります。ファイルが他の誰かによって削除された場合、それはチェック例外です。

チェック例外は2つの方法で処理できます。これらは、try-catchを使用しているか、例外を伝播しています。例外の伝播の場合、例外処理のため、コールスタック内のすべてのメソッドが密結合されます。そのため、チェック例外を注意深く使用する必要があります。

レイヤードエンタープライズシステムを開発する場合、ほとんどチェックされていない例外をスローするように選択する必要がありますが、何もできない場合はチェックされた例外を使用することを忘れないでください。


1

チェックされた例外は、呼び出し元に情報を提供する必要がある回復可能な場合(つまり、不十分なアクセス許可、ファイルが見つからないなど)に役立ちます。

未チェックの例外は、実行時にユーザーまたはプログラマーに重大なエラーや予期しない状態を通知するために使用されることはほとんどありません。他の人が使用するコードやライブラリを作成している場合は、コンパイラがそれらを強制的にキャッチまたは宣言しないため、ソフトウェアが未チェックの例外をスローすることを期待していない可能性があるため、それらをスローしないでください。


「チェックされていない例外はめったに使用されない」というあなたの発言には実際には反対です。アプリケーションの例外階層を設計するときは、デフォルトで未チェックの例外を使用します。例外を処理するタイミングを開発者が決定できるようにします(たとえば、例外の処理方法がわからない場合、catchブロックやthrows句を配置する必要はありません)。
user1697575

1

例外が予想される可能性は低く、それをキャッチした後でも処理を続行でき、その例外を回避するために何もできない場合は、チェック済み例外を使用できます。

特定の例外が発生したときに意味のあることを行いたい場合、およびその例外が予期されているが確実ではない場合は、チェック例外を使用できます。

例外が異なるレイヤーで移動するときは常に、すべてのレイヤーでキャッチする必要はありません。その場合、ランタイム例外またはラップ例外を未チェックの例外として使用できます。

ランタイム例外は、例外が発生する可能性が最も高い場合に使用されます。これ以上進む方法はなく、回復可能なものはありません。したがって、この場合、その例外に関して予防策を講じることができます。EX:NUllPointerException、ArrayOutofBoundsException。これらが発生する可能性が高くなります。このシナリオでは、そのような例外を回避するためにコーディング中に予防策を講じることができます。それ以外の場合は、すべての場所でtry catchブロックを記述する必要があります。

より一般的な例外はチェックなしにでき、一般的でないものはチェックされます。


1

私はいくつかの質問から例外を考えることができると思います:

なぜ例外が発生するのですか?それが起こったときに何ができるか

誤って、バグ。nullオブジェクトのメソッドなどが呼び出されます。

String name = null;
... // some logics
System.out.print(name.length()); // name is still null here

この種の例外は、テスト中に修正する必要があります。そうしないと、プロダクションが中断し、すぐに修正する必要がある非常に高いバグが発生します。この種の例外を確認する必要はありません。

外部からの入力では、外部サービスの出力を制御または信頼できません。

String name = ExternalService.getName(); // return null
System.out.print(name.length());    // name is null here

ここで、名前がnullのときに続行する場合は、名前がnullかどうかを確認する必要がある場合があります。そうでない場合は、名前をそのままにしておくと、ここで停止し、呼び出し元に実行時例外が発生します。この種の例外を確認する必要はありません。

外部からの実行時例外により、外部サービスを制御または信頼できません。

ここで、ExternalServiceからのすべての例外をキャッチする必要がある場合は、それが発生したときに続行する必要があります。

外部からのチェック例外によって、外部サービスを制御または信頼できません。

ここで、ExternalServiceからのすべての例外をキャッチする必要がある場合は、それが発生したときに続行する必要があります。

この場合、ExternalServiceで発生した例外の種類を知る必要がありますか?場合によります:

  1. ある種の例外を処理できる場合は、それらをキャッチして処理する必要があります。他の人のために、それらを泡立たせます。

  2. ユーザーに特定の実行に関するログまたは応答が必要な場合は、それらをキャッチできます。他の人のために、それらを泡立たせます。


0

アプリケーション例外を宣言するときは、チェックされていない例外、つまりRuntimeExceptionのサブクラスである必要があると思います。その理由は、try-catchを使用してアプリケーションコードを乱雑にせず、メソッドに宣言をスローするためです。アプリケーションがJava Apiを使用していて、処理する必要があるチェック例外をスローする場合。その他の場合、アプリケーションは未チェックの例外をスローできます。アプリケーションの呼び出し元が未チェックの例外を処理する必要がある場合は、それを行うことができます。


-12

私が使用するルールは、チェックされていない例外を使用しないことです。(またはそれを回避する方法がない場合)

ライブラリを使用している開発者またはライブラリ/アプリケーションを使用しているエンドユーザーの視点から見ると、未熟な例外のためにクラッシュするアプリケーションに直面するのは本当にうんざりです。キャッチオールを当てにするのもよくありません。

これにより、アプリケーションが完全に消えるのではなく、エンドユーザーにエラーメッセージが表示されます。


1
ほとんどのチェックされていない例外のキャッチオールで何が悪いと思うかを説明しません。
Matthew Flaschen

議論の余地のない答えに完全に同意しない:「未チェックの例外を使用しない」
user1697575
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.