第十九章 Exception(例外)
try-catch
スローされた例外をキャッチして、具体的な例外処理を記述します。
try{
//例外をスローする可能性がある処理
}catch(Exception e){
//例外がスローされた場合の処理
}
目次
1.例外をスローさせる
以下のサンプルコードは、要素数3の配列に対して、
インデックス3の要素を参照しています。
要素数3の配列の最終要素はインデックス2ですから、例外をスローします。
基本的に前のページで紹介した
ソースと同じだ。
//Sample19_11.java
class Sample19_11{
public static void main(String[] args){
int[] intArray = {
123,
456,
789
};
System.out.println(intArray[3]);//ココで例外スロー
System.out.println("complete");
}
}
コマンドライン
>cd ws
ws>javac -encoding UTF-8 Sample19_11.java
ws>java Sample19_11
Exception in thread "main"
java.lang.ArrayIndexOutOfBoundsException: 3
at Sample19_11.main(Sample19_11.java:11)
ArrayIndexOutOfBoundsExceptionという例外をスローしました。
例外の一種で、RuntimeExceptionクラスのサブクラスになります。
この例外は非チェック例外なので、例外処理が無くてもコンパイルは通りました。
でも実行すると、最後の「complete」の表示がありません。
例外によって強制終了してしまいました。
2.例外処理 try-catch の使い方
例外処理とは
例外のスローに備えた処理のことを例外処理といいます。
そうね。
この前聞いたわ。
この例外に備えた処理を
実際に書いてみよう。
try-catch という方法を使ってみましょう。
try-catch は例外処理の一種です。
例外がスローされた場合の具体的な処理を catchブロックに記述します。
try-catchの書式
try{
//例外をスローする可能性がある処理
}catch(Exception e){
//例外がスローされた場合の処理
}
スローされる例外の種類が複数ある場合には、
スローされた例外の種類に応じて、例外処理を記述することができます。
try-catch の書き方 複数の例外がある場合
try{
//例外をスローする可能性がある処理
} catch(sub01Exception e1)
//sub01Exceptionをキャッチした場合の処理
} catch(sub02Exception e2)
//sub02Exceptionをキャッチした場合の処理
} catch(sub03Exception e3)
//sub03Exceptionをキャッチした場合の処理
}
書式の説明
- tryブロックの中に、「例外をスローする可能性がある処理」を記述します。
- 例外がスローされると tryブロックの処理は中断されて、
例外の型に対応した catchブロックの処理が実行されます。
- catchの引数(ここでは e)には、スロー(throw)された Exceptionクラス(又はそのサブクラス)のインスタンスが代入されます。
これを「例外をキャッチする」と言います。
catchの引数名には、慣習として「e」が使用されることが多いです。
- この変数 eのスコープは catchブロック内のみです。
- catchブロックの中が実行されます。
- catchブロック実行後は、強制終了せずに、続きを実行します。
throw については後述します。
try-catch のブロックは変数のスコープに影響します。
必要に応じてブロックの外で宣言しましょう。
3.try-catch の使用例
Sample19_11に、try-catchで
例外処理を追加してみた。
//Sample19_12.java
class Sample19_12{
public static void main(String[] args){
int[] intArray = {
123,
456,
789
};
try{
System.out.println(intArray[3]);
}catch(ArrayIndexOutOfBoundsException e){ //1
System.out.println("catch block"); //2
System.out.println(e);//例外の表示
}
System.out.println("complete"); //3
}
}
コマンドライン
ws>javac -encoding UTF-8 Sample19_12.java
ws>java Sample19_12
catch block
java.lang.ArrayIndexOutOfBoundsException: 3 ←例外の表示
complete
- tryブロック内で、Java仮想マシンから
例外 ArrayIndexOutOfBoundsException がスローされました。
- 例外がスローされたので catchブロックが実行されました。
「catch block」が表示されて、
エラーの種類が表示されました。
- 強制終了はせずに「complete」が表示されました。
System.out.println(intArray[
3]); は実行できませんでしたが、
その後
強制終了されることなく処理を続けたことがわかります。
お~。
例外が出ても
続けられるんすね。
ただ、tryブロックの中の処理は
途中で止めてしまった。
続けられるのは分かったけど、
続けていいのか悪いのか、
場合によっては疑問よね。
その通り。
例外をすべてキャッチする必要はない。
あえて強制終了させるのも選択肢だ。
4.try-catch は if-else文に似ている?
ヒントになるかわかりませんが、少し補足です。
try-catch は、「処理を分岐する」という点で if-else文 に少し似ています。
特徴は以下のような部分です。
if-else は、booleanによって処理を分岐しますが、
try-catch は、例外の有無と種類で処理を分岐します。
if-else は、
初めに booleanによる分岐が行われて、実行される処理が決定しますが、
try-catch は、
例外がスローされるまでの間、tryの中を実行し続けます。
常に例外が監視されていて、例外がスローされた時点で、catchに分岐します。
Exception の種類が煩わしい
かもしれないが、
処理の流れはただの分岐なんだ。
5. Exception.printStackTraceメソッド
printStackTraceメソッドは、Exceptionクラスのインスタンスメソッドです。
(厳密には、java.lang.Throwableクラスの から継承しています。)
ご参照→ クラスの継承関係
printStackTraceメソッドは、例外の詳細なメッセージを表示します。
以下の Sample19_13 のように、catchブロックの中で使用すると。
スローされた例外の情報がコマンドラインに表示されます。
デバッグに便利なのはこれだ。
例外がスローされるべきでないときに使おう。
//Sample19_13.java
class Sample19_13{
public static void main(String[] args){
int[] intArray = {
123,
456,
789
};
try{
System.out.println(intArray[3]);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("catch block");
e.printStackTrace();//例外の表示
}
System.out.println("complete");
}
}
コマンドライン
ws>javac -encoding UTF-8 Sample19_13.java
ws>java Sample19_13
catch block
java.lang.ArrayIndexOutOfBoundsException: 3
at Sample19_13.main(Sample19_13.java:12)
complete
尚メッセージは、例外の種類とスローした場所を示しています。
この場合は、
ArrayIndexOutOfBoundsExceptionが
引数 3 によって
Sample19_13クラスの
mainメソッドでスローしました。
(Sample19_13.javaファイルの 12行目です。)
という具合です。
具体的な情報が
表示されるのは助かるわ。
6. 例外時にメソッドを終了するサンプル
例外をキャッチしたらメソッドを終了したい場合は、catchロックの終わりに return を記述します。
強制終了させるのではなく、
穏便に終了したい場合はこれだな。
//Sample19_14.java
class Sample19_14{
public static void main(String[] args){
int[] intArray = {
123,
456,
789
};
try{
System.out.println(intArray[3]);
}catch(ArrayIndexOutOfBoundsException e){
e.printStackTrace();//例外の表示
System.out.println("中断");
return;//mainメソッド終了
}
System.out.println("complete"); //例外時には実行されない
}
}
コマンドライン
ws>javac -encoding UTF-8 Sample19_14.java
ws>java Sample19_14
java.lang.ArrayIndexOutOfBoundsException: 3
at Sample19_14.main(Sample19_14.java:12)
中断
return って
こんな風に使えるんすね~。
7.スローされる例外の名前の調べ方
この何とかエクセプション?てやつ
覚えなきゃいけないの?
私は覚えられないから
あえて例外をスローさせて
出てきたメッセージをコピペしてる。
コマンドライン
ws>javac -encoding UTF-8 Sample19_11.java
ws>java Sample19_11
>Exception in thread "main"
java.lang.ArrayIndexOutOfBoundsException: 3 ←ココ
at Sample19_11.main(Sample19_11.java:11)
このメソッドは try-catch したよな~
ぐらいで大丈夫だと思う。
なるほど。
それなら綴りまでは覚えなくても
大丈夫そうですね。
例外の名前の調べ方
例外の名前は綴りも長くて覚えにくいですね。
例外処理を書かないで例外をスローさせると、
必要な例外の名前が表示されます。
これをコピペすると便利ですよ。
try-catch してe.printStackTraceメソッドでもいいですね。
8.例外の名前がめんどくさい場合
あんまりおすすめしたくないんだけど。
何の例外でも
とりあえずキャッチするならこれで。
//Sample19_15.java
class Sample19_15{
public static void main(String[] args){
int[] intArray = {
123,
456,
789
};
try{
System.out.println(intArray[3]);
}catch(Exception e){
System.out.println("catch block");
e.printStackTrace();//例外の表示
}
System.out.println("complete");
}
}
コマンドライン
ws>javac -encoding UTF-8 Sample19_15.java
ws>java Sample19_15
catch block
java.lang.ArrayIndexOutOfBoundsException: 3
at Sample19_15.main(Sample19_15.java:12)
complete
これでいいじゃん!
え~っ!
お疲れ様でした。