4

例外を呼び出しスタックに伝播させるという概念、または実際の有用性を完全に理解するのに苦労しています。それらを作成する方法はわかりますが、数学などの単純な実世界のアプリケーションのように、いつ使用されるかは実際にはわかりません。

public void method1(){
    try{
        method2();
    }
    catch(Exception e){
        e.printStackTrace();
    }
}

public void method2(){
      try{
          throw new Exception();
      }
      finally{
         System.out.println("no exception, try cleanup");
      }
}

これは基本的にはどのように機能するかを理解していますが、おそらくより多くの例外や関数に関係しているでしょうが、すべての関数でキャッチを使用する代わりにこれらを使用する意味はありません。

4

4 に答える 4

5

...しかし、すべての関数でキャッチを使用する代わりに、これらを使用する意味がわかりません。

重要なのは、呼び出しスタックの次の関数が例外の処理方法を知らない可能性があるということです。例:

public class Test {

    public Object doSomething(String source) throws IOException {
        try (InputStream is = openAsStream(source)) {
            // ... read and process stuff
            return ...
        }
    }

    public InputStream openAsStream(String name) throws IOException {
        String fileName = // ... do something with 'name'
        return new FileInputStream(name);
    }

    public static void main(String[] args) {
        // ...
        Test t = new Test();
        try {
            t.doSomething(args[0]);
        } catch (IOException ex) {
            System.err.println("Cannot handle '" + args[0] + "'");
        }
    }
}

。をスローする可能性openAsStreamのあるコンストラクターを呼び出します。メソッドはこれから回復できないため、伝播させます。メソッドもそれを処理する方法を知らないので、それはそれが伝播することを可能にします。最後に、例外は...に到達します。これは、ユーザーに問題を説明する方法を知っています。FileInputStreamIOExceptionopenAsStreamdoSomethingmain


openAsStreamこれで、をキャッチしIOException、エラーメッセージを出力して、を返すように記述できますnull。しかし、それは大きな間違いです。

  • は、問題をユーザーに報告するかどうか/どのように報告するかを知り openAsStream()ません(そして知らないはずです)。

  • そして、それが呼び出し元にaを返す場合null、呼び出し元は、呼び出しの結果がnull...であるかどうかを確認するためにテストし、代替アクションを実行する必要があります。

重要なのは、メソッドはそのレベルで適切に処理できる例外のみを処理する必要があるということです。他のものは繁殖することを許可されるべきです。(または、別の例外にラップされている可能性があります...それがAPI設計に必要な場合)。

于 2013-03-26T02:19:42.207 に答える
2

例外の伝播により、デフォルトでエラー時にコードがフェイルファストになります。

例外伝播の代替アプローチを検討してください-エラーコードを返します。コードの呼び出し元が誤ってまたは故意にエラーコードをテストしない場合、メソッドを使用し、オブジェクトが現在使用できない状態にあることに気付かずに、メソッドの呼び出しを続行し、未定義の動作/メモリの破損を引き起こす可能性があります。代わりに例外をスローした場合、呼び出し元が例外をキャッチするのを忘れた場合、恐ろしいことをする代わりに、それらはすぐに失敗し、プログラマーはそれがスローされた場所、理由、およびそれに対して何をすべきかについて警告を受けることができます。例外は、考慮する必要のある条件を示しているため、大音量で不快です。

于 2013-03-26T02:02:51.393 に答える
1

例外を生成するコードが、例外を適切に処理する方法を知らない場合があります。トランザクションコードの一部にいて、何かが爆発した場合、そのメソッド/コンポーネントは、例外を処理しようとした場合に、単に例外をログに記録する以上のことを実行できない可能性があります。一方、1つ以上のレイヤーを上にすると、接続の再確立を試みたり、リクエスターに詳細なエラー応答を提供したりできる場合があります。

于 2013-03-26T01:48:55.757 に答える
1

多くの場合、呼び出し元は問題に対処するための適切なコンテキストを持っていますが、例外を生成するアクションを実行するコードはそうではありません。私がファイルにデータを書きたい高水準プログラムだとしましょう。私が呼んでいる低レベルのサービス、それをwriteFile()と呼ぼうとすると、さまざまな理由でIOExceptionがスローされる可能性があります。

writeFile()を書いた人は、writeFile()が使用されるコンテキストを知らないでしょう。writeFile()が失敗した場合、ファイルの再書き込みを試行する必要がありますか?何回試してみるべきですか?それはただあきらめるべきですか?あるタスクを実行するスキームで低レベル関数writeFile()のコンテキストを記述したプログラマーは、雑草のはるか下にあるため、プログラマーは、呼び出し元がエラー状態をどのように処理するかを予測できませんでした。

呼び出し元がエラーをどのように処理するかを推測しようとする代わりに(不可能なタスク)、writeFile()のプログラマーは、writeFile()を呼び出すクライアントに、問題が発生したときに答える必要のある「未解決の質問」があることを示します。発生します。各問題は例外クラスによって示され、クライアントプログラマーがその例外をキャッチすると、クライアントプログラマーは、クライアントプログラマーが決して望んでいないコンテキストで、その未解決の質問に対する回答を記述します。

要するに、チェックされた例外をリストするメソッドを見たことがあれば、その例外を書いたプログラマーは、「Whomeverがこのメソッドを呼び出すと、その例外条件をどうするかを決定するための適切なコンテキストがあります。私はしません」と言っています。

于 2013-03-26T01:58:34.927 に答える