Javaでは例外(Exception)が発生するので、その例外を適切に処理する記載をしておかないとコンパイルエラーになります。例外の処理方法は2つあります。
- try 〜 catch文により例外をキャッチする。
- メソッドの宣言にthrows句を記載して、呼び出し元に例外を引き渡す。
Javaでは例外処理を記載することが原則ですが、当てはまらないケースが1つあります。それは RuntimeException を継承したクラスの例外です。
RuntimeException を継承したクラスには ArrayIndexOutOfBoundsException(配列の添字が不正の時に発生する)や ArithmeticException(ゼロで除算した場合に発生する)などがあります。
例外処理の記載がない場合、RuntimeException はJavaの実行環境までスローされます。
以下の青色の例外は例外処理を記載しなくてもコンパイルエラーにはなりません。
実際にサンプルプログラムで動きを確かめてみました。
通常の例外の場合です(RuntimeExceptionでない例外のことです)。独自の例外クラスを作成し、例外処理を記載しました。
ThrowException1の中でSampleExceptionという例外を発生させ、MainSample1で例外をキャッチします。
ソースコードは以下です(テキストエディタの画像を貼り付けたのでコードは最後に記載しておきます)。
SampleException.java
– – – – –
ThrowException1.java
– – – – –
ThrowException2.java
– – – – –
MainSample1.java
– – – – –
実行結果です。
$ java sample4.MainSample1 この例外は発生しません 例外をcatchしました sample4.SampleException: SampleExceptionが発生しました
MainSample1の e2.exampleException(1); を実行したときは例外が発生しないためThrowException1の中で「この例外は発生しません」の文言を出力しています。e2.exampleException(-1); を実行したときにSampleExceptionの例外が発生したためMainSample1で例外をキャッチして処理を終わらせています。
なお、MainSample1で try〜catch 文を使わなかった場合、次のようなコンパイルエラーになります。
$ javac sample4/MainSample1.java sample4/MainSample1.java:10: エラー: 例外SampleExceptionは報告されません。スローするには、捕捉または宣言する必要があります e2.exampleException(1); ^ sample4/MainSample1.java:11: エラー: 例外SampleExceptionは報告されません。スローするには、捕捉または宣言する必要があります e2.exampleException(-1); ^ sample4/MainSample1.java:12: エラー: 例外SampleExceptionは報告されません。スローするには、捕捉または宣言する必要があります e2.exampleException(2); ^ エラー3個
ThrowException2のexampleExceptionメソッドに throws SampleException を付けなかった場合は、次のようなコンパイルエラーになります。
$ javac sample4/ThrowException2.java sample4/ThrowException2.java:8: エラー: 例外SampleExceptionは報告されません。スローするには、捕捉または宣言する必要があります e1.exampleException(i); ^ エラー1個
RuntimeException が発生する場合です。
メソッドにthrows句を記載しなくても例外は呼び出し元に返されます。MainSample2では例外をキャッチする記載(try〜catch文)がないため、例外はJavaの実行環境まで返されます。
ソースコードは以下です。
ThrowRuntime1.java
– – – – –
ThrowRuntime2.java
– – – – –
MainSample2.java
– – – – –
実行結果です。
$ java sample5.MainSample2 この例外は発生しません 配列に値を格納しました Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 at sample5.ThrowRuntime1.exampleException(ThrowRuntime1.java:12) at sample5.ThrowRuntime2.exampleException(ThrowRuntime2.java:8) at sample5.MainSample2.main(MainSample2.java:10)
MainSample2の e2.exampleException(1); を実行したときは例外が発生しないためThrowRuntime1の中で「この例外は発生しません」の文言を出力しています。e2.exampleException(-1); を実行したときにArrayIndexOutOfBoundsExceptionの例外が発生してJava実行環境まで渡されます。Java実行環境は例外の内容を標準出力しています。
ちなみにこのケースですが、ThrowRuntime1で例外を発生させたあとに「配列に値を格納しました」の出力をするようにしました。例外が発生しているため処理が中断されるのかと思ったのですが、そうでもないようです。実行結果として「配列に値を格納しました」の文言が出力されているので、そのあとに例外をスローしているようです。
ここで使用したソースコードを記載しておきます。
SampleException.java
package sample4;
public class SampleException extends Exception {
//コンストラクタ(同じパッケージにのみ公開)
SampleException(String s) {
//スーパークラスのコンストラクタを呼び出す
super(s);
}
}
ThrowException1.java
package sample4;
public class ThrowException1 {
void exampleException(int i) throws SampleException {
if ( i > 0 )
System.out.println("この例外は発生しません");
else
throw new SampleException("SampleExceptionが発生しました");
}
}
ThrowException2.java
package sample4;
public class ThrowException2 {
void exampleException(int i) throws SampleException {
ThrowException1 e1 = new ThrowException1();
e1.exampleException(i);
}
}
MainSample1.java
package sample4;
public class MainSample1 {
public static void main( String[] args ) {
ThrowException2 e2 = new ThrowException2();
try {
e2.exampleException(1);
e2.exampleException(-1);
e2.exampleException(2);
} catch ( SampleException e ) {
System.out.println("例外をcatchしました");
System.out.println(e);
}
}
}
ThrowRuntime1.java
package sample5;
public class ThrowRuntime1 {
void exampleException(int i) {
int[] a = new int[3];
if ( i > 0 )
System.out.println("この例外は発生しません");
else
a[3] = 1;
System.out.println("配列に値を格納しました");
}
}
ThrowRuntime2.java
package sample5;
public class ThrowRuntime2 {
void exampleException(int i) {
ThrowRuntime1 e1 = new ThrowRuntime1();
e1.exampleException(i);
}
}
MainSample2.java
package sample5;
public class MainSample2 {
public static void main( String[] args ) {
ThrowRuntime2 e2 = new ThrowRuntime2();
e2.exampleException(1);
e2.exampleException(-1);
e2.exampleException(2);
}
}