throw
例外を検出して捕捉することを「例外を catch(キャッチ)する」と、上記でいいました。今回は逆に、例外オブジェクトを throw(スロー)することにより任意の場所で例外を発生するやり方を見てみましょう。
例外を発生させることを例外をthrow(スロー)するといいます。これは、自分でクラスを作った場合に、どうしても例外を自分で呼び出したいケースが出てくる場合があります。そのような時に、この throwを使用します。
[ 構文 ]
throw(new 例外クラス名);
throw キーワードの後には
Throwable クラスから派生した例外オブジェクトを指定します。これにより、スローされる例外の型が決まります。throw ステートメントは即座にプログラムを中断し、指定した例外オブジェクトを処理できる最も近い catch ブロックへ制御を移します。
[ Example_12_02.java ]
public class Example_12_02 {
public static void main(String args[]){
try{
ProcessA.FunctionA();
}catch(ArithmeticException e){
System.out.println("例外が発生しました");
}
}
}
class ProcessA {
static void FunctionA(){
throw(new ArithmeticException());
}
}
このプログラムが実行されると、ProcessAクラスの FunctionAメソッドが呼ばれ、このメソッド内の throwステートメントで ArithmecticException()のインスタンスを生成してスローしています。
呼び出し元では例外が生成されたことを受け、変数 eに ArithmecticExceptionオブジェクトが渡されて、プログラムはすぐに catchブロックを実行します。このように、プログラムで明示的に例外を呼び出すことができます。
throws
上のサンプルをみて疑問に感じた方もいるかと思います。 FunctionAで発生した例外であるのに、catchブロックは呼び出し元の catchブロックが実行されていますね。
Javaでは例外が発生したメソッド内で例外ハンドラを発見できない場合、例外ハンドラを求めてメソッド呼び出し元を逆に捜しに行きます。
つまり上のサンプルでは、FunctionA内に例外ハンドラが存在しないため、JVMが例外ハンドラを呼び出しもとのメソッドまでさかのぼって探したわけです。 実際、例外が発生するかもしれない各メソッド全てに例外ハンドラを用意するのはかなりの手間がかかります。このような時にメソッドで発生する可能性がある例外を明示的に「
throws句 」で記述して、呼び出し元のメソッドへ例外処理を任せることが出来ます。
[ 構文 ]
メソッド名 ( 引数型 引数名 ) throws 例外クラス1 , 例外クラス2 {
}
[ Example_12_03.java ]
import java.io.*;
public class Example_12_03 {
public static void main(String[] args) {
Example_12_03 obj = new Example_12_03();
obj.methodA();
}
void methodA() {
try {
methodB();
} catch (FileNotFoundException e) {
System.err.println(e.getMessage()); // ※2
} finally {
System.out.println("MethodA was finished");
}
}
void methodB() throws FileNotFoundException { // ※1
FileReader exFile = new FileReader("exFile.txt");
}
}
[ 実行結果 ]
exFile.txt (指定されたファイルが見つかりません。)
MethodA was finished
※ 1.
MethodB内で FileReaderオブジェクト exFileの生成を行っています。例外 FileNotFoundExceptionが発生した場合、throwsで指定された例外クラス型に基づいて、呼び出し元メソッド MethodAに例外オブジェクトを throw(スロー)します。
※ 2.
catchステートメントにて例外クラス FileNotFoundExceptionをキャッチし、getMessageメソッドを使用して例外オブジェクトに含まれるメッセージを出力します。
例外ハンドラが見つからない場合
呼び出し元のメソッドでも例外ハンドラが用意されていなければ、さらにその呼び出し元という感じで JVMは例外ハンドラを検索します。しかしどこにも例外ハンドラが用意されていなかった場合、JVM は例外としてプログラムの実行を停止します。