web-dev-qa-db-ja.com

メソッドが例外をスローしないのに、コンパイラがスローを許可するのはなぜですか

Javaコンパイラは、メソッドが例外をスローしない場合に、メソッド宣言でスローを許可する理由を知りたいと思います。「スロー」は、例外を処理する方法(呼び出し側に処理を通知する)なので) 。

例外を処理する方法が2つあるため(スローとtry/catch)。 try/catchでは、tryブロックでスローされない例外のキャッチは許可されませんが、例外をスローしない可能性のあるメソッドでのスローは許可されます。

private static void methodA() {
    try {
        // Do something
        // No IO operation here
    } catch (IOException ex) {  //This line does not compile because
                              //exception is never thrown from try
        // Handle   
    }
}

private static void methodB() throws IOException { //Why does this //compile when excetion is never thrown in function body
    //Do Something 
    //No IO operation
}
18
PsyAp

throws句は、メソッドの規約の一部です。メソッドの呼び出し元は、指定された例外がメソッドによってスローされる可能性があるように動作する必要があります(つまり、例外をキャッチするか、独自のthrows句を宣言します)。

メソッドの初期バージョンはthrows句で指定された例外をスローしない可能性がありますが、将来のバージョンはAPIを壊すことなくそれをスローできます(つまり、メソッドを呼び出す既存のコードは引き続きコンパイルに合格します) 。

反対も可能です。メソッドがthrows句で指定された例外をスローするために使用されていたが、将来のバージョンではそれをスローしない場合、既存のコードを壊さないためにthrows句を保持する必要がありますそれはあなたの方法を使用します。

最初の例:

methodBを使用する次のコードがあるとします。

private static void methodA() {
    methodB(); // doesn't have throws IOException clause yet
}

後でmethodBを変更してIOExceptionをスローする場合、methodAはコンパイルのパスを停止します。

2番目の例:

methodBを使用する次のコードがあるとします。

private static void methodA() {
    try {
        methodB(); // throws IOException
    }
    catch (IOException ex) {

    }
}

将来のバージョンのthrowsからmethodB句を削除すると、methodAはコンパイルをパスしなくなります。

この例は、methodAprivateである場合、ローカルでは(同じクラス内で、それを呼び出すすべてのメソッドを簡単に変更できるため)使用できるため、あまり興味深いものではありません。

ただし、それがpublicになると、誰がそのメソッドを使用するか(または使用するか)がわからないため、throws句。

そして、それがインスタンスメソッドである場合、例外をスローしなくてもthrows句を許可する別の理由があります-メソッドはオーバーライドでき、オーバーライドするメソッドは、基本クラスの実装であっても例外をスローする場合がありますではない。

26
Eran

シグネチャはメソッドのコントラクトを定義するためです。メソッドが今すぐIOExceptionをスローしない場合でも、将来的にはその可能性があり、その可能性に備える必要があります。

ここでは、メソッドのダミー実装を提供するだけで、後で実際の実装がIOExceptionをスローする可能性があることを知っているとします。コンパイラーがこのthrows節を追加できない場合、メソッドの実際の実装を提供すると、そのメソッドへのすべての呼び出しを(再帰的に)やり直す必要があります。

8
JB Nizet

キーワードスローは、メソッドでIOExceptionが発生している可能性があることをプログラマに通知します。ここで、try/catchを指定しなかった場合は、例外がスローされるとプログラムが機能しなくなりますが、try/catchでは、例外がスローされた場合に何かを実行して処理します。

読みやすさのためにスローを使用し、例外の可能性を指定し、try/catchを使用して、例外の場合に何をすべきかをプログラムに伝えます。

0
IvanM