関数を呼び出すときに「スロー例外」が必要なのはなぜですか?


97
class throwseg1
{
    void show() throws Exception
    {
        throw new Exception("my.own.Exception");
    }

    void show2() throws Exception  // Why throws is necessary here ?
    {
        show();
    }

    void show3() throws Exception  // Why throws is necessary here ?
    {
        show2();
    }

    public static void main(String s[]) throws Exception  // Why throws is necessary here ?
    {
        throwseg1 o1 = new throwseg1();
        o1.show3();
    }
}

なぜコンパイラレポートその方法show2()show3()およびmain()持っています

報告されない例外スローするためにキャッチまたは宣言する必要のある例外

throws Exceptionこれらのメソッドから削除するとどうなりますか?


2
@PaulTomblin mainは、例外をスローするように宣言できます。その場合、JVMはシャットダウンします。これは、コンパイラが許可する限り、無視することと同じです。
タイモン2012

呼び出されるメソッド(ときMethdod1が)スローException、我々は呼び出すメソッド(定義する必要が方法2を持ちます)throws Exception。呼び出しメソッドでその例外を渡さない場合。この目的は、呼び出すメソッド(に頭を放棄することである法3の)方法2例外によってスローすることができることを方法2それはあなたのプログラムを中断して、他の、そしてあなたはここでそれを処理する必要があります。
Rito

同様に、Method3が本体で例外を処理していない場合はthrows Exception、メソッド定義で定義して、呼び出し元のメソッドを解放する必要がありました。以前のコメントの拡張
Rito

回答:


144

ご存知かもしれませんが、Javaでは、例外を2つに分類できます。1つはthrows句を必要とする例外、もう1つは指定せずに処理する必要があるもの、もう1つは不要なものです。次の図を見てください。

ここに画像の説明を入力してください

Javaでは、Throwableクラスを拡張するものをすべてスローできます。ただし、throwsすべてのクラスに句を指定する必要はありません。具体的には、これらの2つのサブクラスのいずれErrorRuntimeExceptionまたはいずれかであるクラス。あなたのケースでExceptionは、ErrorまたはのサブクラスではありませんRuntimeException。したがって、これはチェックされた例外でありthrows、特定の例外を処理しない場合は、句で指定する必要があります。そのため、このthrows句が必要でした。


Javaチュートリアルから:

例外は、プログラムの実行中に発生するイベントで、プログラムの命令の通常のフローを中断します。

さて、あなたが知っているように、例外はチェックされたものとチェックされていないものの2つに分類されます。なぜこれらの分類なのか?

チェック例外:プログラムの実行中に回復できる問題を表すために使用されます。通常、これらはプログラマの責任ではありません。たとえば、ユーザーが指定したファイルが読み取り可能ではない、ネットワーク接続が利用できない、などです。これらすべての場合に、プログラムを終了する必要はありません。代わりに、ユーザーに警告したり、フォールバックしたりすることができます。メカニズム(ネットワークが利用できない場合のオフライン作業など)など

未チェックの例外:これらは、エラーとランタイム例外の 2つに分類できます。それらがチェックされていない理由の1つは、それらの数が多く、それらすべてを処理する必要があるため、プログラムが乱雑になり、その明快さが低下することです。他の理由は:

  • 実行時例外:通常、これらはプログラマーの障害が原因で発生します。たとえば、ArithmeticExceptionゼロによる除算が発生したArrayIndexOutOfBoundsException場合、または発生した場合は、コーディングに十分注意していないためです。これらは通常、プログラムのロジックにエラーがあるために発生します。したがって、プログラムをプロダクションモードにする前にクリアする必要があります。私たちのプログラマーが開発時およびテスト時にそれを解決できるように、プログラムが発生したときに失敗する必要があるという意味で、それらはチェックされていません。

  • エラー:エラーは通常、プログラムが回復できない状況です。たとえば、a StackOverflowErrorが発生した場合、プログラムの関数呼び出しスタックのサイズを増やすなど、プログラムは多くのことを実行できません。または、問題OutOfMemoryErrorが発生した場合、プログラムで使用できるRAMの量を増やすために多くのことを行うことはできません。このような場合は、プログラムを終了することをお勧めします。それがチェックされていない理由です。

詳細については、以下を参照してください。


私があなたの答えから得たのは、Errorクラスとそのサブクラス、RuntimeExceptionクラスとそのサブクラス、それらはチェックされていない例外(System.out.println(5/0など)のもとにあります)なので、スローする必要はありません実行時例外ですが、それでもトライキャッチを適用できます)、例外クラスがチェックされているため、そのメソッドとそれを呼び出すすべてのメソッドでスロー句を宣言する必要があります
nr5

もう1つの質問:例外がチェックされていないものとチェックされているものに分類される場合、特にチェックされていないもの(ランタイムエラー)は、コンパイル時のエラーの数を増やすためですか?
nr5 2012

@Jomoos-メソッド内のコードがIOExceptionをスローするとします。次に、メソッドの宣言に「例外をスロー」を入れても大丈夫ですか?
MasterJoe

ああ。わかった。例外階層のルールには例外があります。作る。完璧です。センス。Javaに感謝します。
JJS 2018年

25

Javaでは、すべての例外を処理または宣言する必要があります。try / catchブロックを使用して例外を処理していない場合は、メソッドのシグネチャで宣言する必要があります。

例えば:

class throwseg1 {
    void show() throws Exception {
        throw new Exception();
    }
}

次のように書く必要があります:

class throwseg1 {
    void show() {
        try {
            throw new Exception();
        } catch(Exception e) {
            // code to handle the exception
        }
    }
}

このようにして、メソッド宣言の「スロー例外」宣言を取り除くことができます。


7
RuntimeExceptionつまり、のサブクラスではないすべての例外。
yshavit 2012

チェックされる例外のような他のクラスがある場合?
nr5 2012

1
どういう意味ですか?すべての例外オブジェクトは基本クラスとして「例外」を持っているため、「例」のように「例外」オブジェクトをキャッチすると、スローされたすべての例外をキャッチします。より具体的にするためには(例外が異なると、処理の方法も異なるため、おそらく複数のcatchブロックが必要です)。
jebar8

チェックされた例外は、@コンパイル時に処理し、実行時にキャッチする必要があると言った場合。私は正しいですか?はいの場合、チェックされていない例外について同じ文を使用すると、
nr5 2012

@ jebar8-Javaと.NETを混同しています-Javaでは、スロー可能オブジェクトは継承する必要がありますThrowable(継承Exceptionも機能します。継承は機能するためですがThrowable、必須ではありません)。
BrainSlugs83

4

Exceptionチェックされた例外クラスです。したがって、それthrows Exceptionを処理または宣言する必要があることを宣言するメソッドを呼び出すコード。


チェーン内のすべてのメソッドは、メインを含む例外をスローするように宣言されています。では、問題はどこにあるのでしょうか?
ポールトンブリン

@PaulTomblinは、呼び出し側の関数で例外をスローするように記述する必要があるのではないかと尋ね、例外をスローする関数を呼び出します
nr5

わかりました。投稿したコードから実際に得られなかったコンパイラエラーについて尋ねた理由がわかりませんでした。それは奇妙な方法です。
ポールトンブリン

4

throws Exception宣言が予想されるが、やむを得ない理由のために例外をスローする可能性があります方法を追跡する自動化された方法です。宣言は通常、throws IOExceptionまたはなどのスローされる可能性のある例外のタイプ(複数可)に固有throws IOException, MyExceptionです。

ゼロによる除算や範囲外のインデックスなど、プログラムを実行する前に予期していなかったことが原因で、予期せず停止して例外を報告するコードを作成するか、最終的に作成します。エラーはメソッドによって予期されていなかったため、「キャッチ」できず、try catch句で処理できませんでした。メソッドの疑いを持たないユーザーもこの可能性を知らず、プログラムも停止します。

プログラマーが特定のタイプのエラーが発生する可能性があることを知っているが、メソッドの外でこれらの例外を処理したい場合、メソッドは、1つ以上のタイプの例外を、それらを処理する代わりに、呼び出しメソッドに「スロー」できます。プログラマがメソッドが例外をスローする可能性があることを宣言しなかった場合(またはJavaがそれを宣言する能力を持っていなかった場合)、コンパイラは知ることができず、メソッドの将来のユーザーが知る必要があります。メソッドがスローする可能性のある例外をキャッチして処理します。プログラムには多くの異なるプログラムによって作成されたメソッドの多くの層が存在する可能性があるため、どのメソッドが例外をスローするかを追跡することが困難(不可能)になります。

Javaには例外を宣言する機能がありますが、未処理の例外と宣言されていない例外を使用して新しいメソッドを記述できます。Javaはそれをコンパイルして実行し、最善の結果を期待できます。メソッドで宣言された例外を処理するか、同じをスローするようにメソッドを宣言しない限り、Javaが実行できないのは、例外をスローするように宣言されたメソッドを使用する場合、新しいメソッドをコンパイルすることです。例外または複数の例外がある場合は、いくつかを処理して残りをスローできます。

メソッドが特定の種類の例外をスローすることをプログラマが宣言する場合、それはメソッドを使用する他のプログラマに例外が発生する可能性があることを警告する自動化された方法にすぎません。プログラマは、同じ例外をスローするように呼び出しメソッドを宣言することにより、例外を処理するか警告を渡すかを決定できます。コンパイラーはこの新しいメソッドで例外が発生する可能性があると警告されているため、新しいメソッドの将来の呼び出し元が例外を処理するかどうかを自動的にチェックしたり、例外を宣言してどちらか一方を強制したりできます。

このタイプのソリューションの良い点は、コンパイラーが報告Error: Unhandled exception type java.io.IOExceptionすると、例外をスローするように宣言されたメソッドのファイルと行番号を提供することです。その後、単純にドルを渡すことを選択し、メソッドに「IOExceptionをスローする」ことを宣言することもできます。これはmainメソッドまで実行でき、プログラムが停止してユーザーに例外を報告します。ただし、例外をキャッチして、何が起こったのか、どのように修正するのかをユーザーに説明するなど、適切な方法で対処することをお勧めします。メソッドが例外をキャッチして処理すると、メソッドは例外を宣言する必要がなくなります。ドルは、いわばそこに止まります。


0
package javaexception;


public class JavaException {
   void show() throws Exception
    {
        throw new Exception("my.own.Exception");
    }

void show2() throws Exception  // Why throws is necessary here ?
{
    show();
}

void show3() throws Exception  // Why throws is necessary here ?
{
    show2();
}
public static void main(String[] args) {

   JavaException a = new JavaException();

   try{
   a.show3();
   }catch(Exception e){
       System.out.println(e.getMessage());
   }
}

プログラムの小さな変更のみ。主な問題に関して多くの人が誤解しているように見えるのは、例外をスローするときはいつでも、それを処理する必要があり、同じ場所で必要ではない(例:プログラムのshow1,2,3メソッド)が、最初に呼び出し側のメソッドを実行する必要がある「メイン」の内部。一言で言えば、例外が発生する同じメソッドでなくても、「スロー」があり、「キャッチ/トライ」がなければなりません。


0
void show() throws Exception
{
    throw new Exception("my.own.Exception");
}

show()メソッドでチェックされた例外があるため、そのメソッドでは処理されないため、throwsキーワードを使用して例外を伝播します。

void show2() throws Exception //Why throws is necessary here ?
{
show();
}

show2()メソッドでshow()メソッドを使用していて、例外を少なくとも伝播したので、ここで処理する必要があります。ここで例外を処理していない場合は、throwsキーワードを使用しています。そのため、メソッドシグネチャでthrowsキーワードを使用する理由はここにあります。


0

現在のメソッドのシグネチャでthrowsディレクティブを宣言して例外を伝播する場合、行またはコールスタックのどこかで、例外を処理するためにtry / catch構文を使用する必要があります。


このコメントは、検証可能な回答またはその例を提供しないため、コメントセクションに追加する必要があります。- stackoverflow.com/help/how-to-answer
ポール・ドーソン

-1

基本的に、例外をスローするのと同じ場所で例外を処理しない場合は、関数の定義で「例外のスロー」を使用できます。

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