try / catchと例外のスロー


117

これらのコード文は同等ですか?それらの間に違いはありますか?

private void calculateArea() throws Exception {
    ....do something
}

private void calculateArea() {
    try {
        ....do something
    } catch (Exception e) {
        showException(e);
    }
}

3
実際には答えではありませんが、Ned Batchelderの記事Exceptions in the Rainforestに興味があるかもしれません。
Daniel Pryden

1
キャッチで「showException(e)」を使用する代わりに、代わりにキャッチで「eをスロー」するか(または、try / catchをまったく使用しないか)を尋ねていましたか?
MacGyver 2012年

回答:


146

はい、大きな違いがあります-後者は例外を飲み込み(確かにそれを表示します)、一方、最初のものはそれを伝播させます。(私はそれshowExceptionがそれを再投げしないと仮定しています。)

したがって、最初のメソッドを呼び出して「何かを行う」ことが失敗した場合、呼び出し元は例外を処理する必要があります。2番目のメソッドを呼び出すと、「何かをする」失敗した場合、呼び出し側は、すべての例外は表示されません...一般的に悪いことである、場合を除きshowExceptionました本当に間違っていたものは何でも固定例外を、処理され、一般的に確認しましたそれcalculateAreaはその目的を達成しました。

あなたはせずに最初のメソッドを呼び出すことはできませんので、このことを伝えることができるでしょういずれかのキャッチException自分自身をあなたの方法でもそれを投げるかもしれないことを宣言する。


12
「本当に例外を処理しない限り」と言ったら、それは素晴らしい点です。「例外」をキャッチすること自体が実際の例外のインテリジェントな「処理」につながることはめったにないことを付け加えたいと思ったのです。
ビルK

17
+1。ジョン・スキートにはもっと評判が必要だからです。ああ、答えも良かった。
Jonathan Spiller 2013年

20

1つ目throws Exceptionは、呼び出し元がを処理する必要があるためExceptionです。2つ目はException内部的にキャッチして処理するため、呼び出し元は例外処理を行う必要がありません。


つまり、簡単に言うと、常に2番目のものを使用する必要があります。私は正しいですか?最初のものは実際にはプログラムの別のポイントで使用されるメソッドです。それは..私は一緒にさらなる使用のための指示書をgruopすることを決めた理由ですが、私は今、Tは大きな間違いを犯したことを実現することを行ってた
カルロス

9
いいえ、両方のパターンが必要です。メソッドで例外を処理できる場合は2番目のパターンを使用し、そうでない場合は最初のパターンを使用して呼び出し元に通知します。
Andreas Dolk 2010

使用するバージョンは要件によって異なります。基本的に、その例外を処理するために必要なレベルはどれですか。呼び出し元はそれに応じてコーディングする必要があります。呼び出し元が最初のバージョンを呼び出していて、メソッド定義を2番目のバージョンに置き換えた場合、これはチェックされた例外であるため、呼び出し元のコードは例外の処理を強制されます。
samitgaur 2010

16

はい。宣言するバージョンthrows Exceptionは、例外を処理するために呼び出しコードが必要になりますが、明示的に処理するバージョンでは例外を処理しません。

つまり、単に:

performCalculation();

例外を処理する負担を呼び出し元に移す場合と、

try {
    performCalculation();
catch (Exception e) {
    // handle exception
}

6

はい、それらの間には大きな違いがあります。最初のコードブロックでは、呼び出し元のコードに例外を渡します。2番目のコードブロックでは、自分で処理します。どの方法が正しいかは、あなたが何をしているのかに完全に依存します。場合によっては、コードで例外を処理する必要があります(たとえば、ファイルが見つからず、作成したい場合)が、呼び出し元のコードで例外を処理する(ファイルが見つからない)場合があります。新しいものを指定するか作成する必要があります)。

一般的に言えば、一般的な例外をキャッチする必要はありません。代わりに、次のような、特定のもの、キャッチしたいと思うFileNotFoundExceptionIOException、彼らが異なることを意味することができますのでを。


3

スローを使用できない特定のシナリオが1つあり、try-catchを使用する必要があります。「オーバーライドされたメソッドは、その親クラスがスローしているもの以外の追加の例外をスローすることはできません」というルールがあります。try-catchを使用して処理する必要がある追加の例外がある場合。このコードスニペットを検討してください。単純な基本クラスがあります

package trycatchvsthrows;

public class Base {
    public void show()
    {
        System.out.println("hello from base");
    }
}

そしてそれは派生クラスです:

package trycatchvsthrows;

public class Derived extends Base {

    @Override
    public void show()   {
        // TODO Auto-generated method stub
        super.show();

        Thread thread= new Thread();
        thread.start();
        try {
            thread.sleep(100);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // thread.sleep(10);
        // here we can not use public void show() throws InterruptedException 
        // not allowed
    }
}

thread.sleep()を呼び出す必要がある場合、try-catchの使用を強制されます。ここでは使用できません。

 public void show() throws InterruptedException

オーバーライドされたメソッドは追加の例外をスローできないためです。


誰もがこの警告に気づいているわけではないと思います。よく指摘しました。
ivanleoncz

1

「同一」とはあなたが行動を指していると思います。

関数の動作は次のようにして決定できます。

1)戻り値

2)スローされた例外

3)副作用(つまり、ヒープ、ファイルシステムなどの変更)

この場合、最初のメソッドは例外を伝播し、2番目のメソッドはチェック済み例外をスローせず、ほとんどの未チェック例外も飲み込むため、動作は異なります。

ただし、「何かを行う」が例外をスローしないことが保証されている場合、動作は同じになります(最初のバージョンでは、コンパイラーは呼び出し側が例外を処理する必要があります)

-編集-

API設計の観点から見ると、メソッドは契約で完全に異なります。また、クラスExceptionをスローすることはお勧めしません。より具体的なものをスローして、呼び出し側が例外をより適切に処理できるようにします。


1

例外をスローした場合、(これをオーバーライドする)子メソッドが例外を処理する必要があります

例:

class A{
public void myMethod() throws Exception{
 //do something
}
}

A a=new A();
try{
a.myMethod();
}catch Exception(e){
//handle the exception
}

0

多くの場合、呼び出し元が例外を処理するようにします。たとえば、別のメソッドを呼び出す別のメソッドを呼び出すメソッドを呼び出し側に呼び出させ、各メソッドに例外を処理させるのではなく、呼び出し側でそれを処理できるとしましょう。そのメソッドが失敗したときに、メソッドの1つで何かを実行したい場合を除きます。


0

このメソッドの呼び出し元は、この例外をキャッチするか、メソッドのシグネチャで再スローされるように宣言する必要があります。

private void calculateArea() throws Exception {
    // Do something
}

以下のtry-catchブロックの例で。このメソッドの呼び出し元は、すでに処理されているため、例外の処理について心配する必要はありません。

private void calculateArea() {
    try {
        // Do something

    } catch (Exception e) {
        showException(e);
    }
}

0
private void calculateArea() throws Exception {
    ....do something
}

これは例外をスローするため、呼び出し元はその例外を処理する必要がありますが、呼び出し元が例外を処理しない場合、jvmに渡され、プログラムが異常終了する可能性があります。

一方、2番目のケースでは:

private void calculateArea() {
    try {
        ....do something
    } catch (Exception e) {
        showException(e);
    }
}

ここでは、例外は呼び出し先によって処理されるため、プログラムが異常終了する可能性はありません。

トライキャッチが推奨されるアプローチです。

IMO、

  • コンパイラーを説得するために主にチェック例外で使用されるキーワードをスローしますが、プログラムの正常終了を保証するものではありません。

  • キーワードをスローすると、例外処理の責任が
    呼び出し元(JVMまたは別のメソッド)に委任されます。

  • Throwsキーワードは、チェックされた例外にのみ必要です。チェックされていない例外の場合、throwsキーワードは使用されません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.