練習問題のような,1回走らせたら捨ててしまうようなプログラムはともかく, 商品となるようなプログラムにおいては例外処理は必須となる.プログラミン グ言語によっては,例外処理はライブラリやOS(オペレーティングシステム)な ど言語仕様の外で扱う場合も多いが,Java言語では言語仕様にあらかじめ例外 処理を組み込んである.
例外は,さまざまなところで発生する.以下のプログラムを見てみよう.
プログラム
// 入出力をするために必要
import java.io.*;
// キーボードから数字を入力して, 負の数を入力したら終り
class SumInput{
public static void main(String[] args) throws IOException{
// 入力をするためには,System.inからBufferedReaderを作らなくてはいけない
BufferedReader d=new BufferedReader(new InputStreamReader(System.in));
int sum=0,num=0;
// 条件式が常に trueなので,ループの終了は break でおこなう.
while(true){
String s;
// 一行入力して文字列型変数 s に入れる
s=d.readLine();
// 整数値に変換する
num=Integer.parseInt(s);
// 負の値の時は while 文から抜ける
if(num<0) break;
sum+=num;
}
System.out.println(sum);
}
}
実行例(下線がついているのが入力)
ca20121$ java SumInput
3
2
-1
5
これで,数でないものを代入すると,次のように例外が表示されてプログラム
の実行を中断する.
ca20121$ java SumInput soko java.lang.NumberFormatException: soko at java.lang.Throwable.このような例外が起きた時に,中断せずにプログラムで処理するために用意さ れているのが,try文である.例を見てみる.(Compiled Code) at java.lang.Exception. (Compiled Code) at java.lang.RuntimeException. (Compiled Code) at java.lang.IllegalArgumentException. (Compiled Code) at java.lang.NumberFormatException. (Compiled Code) at java.lang.Integer.parseInt(Compiled Code) at java.lang.Integer.parseInt(Compiled Code) at SumInput.main(Compiled Code)
プログラム
// 入出力をするために必要
import java.io.*;
// キーボードから数字を入力して, 負の数を入力したら終り
class SumInput{
public static void main(String[] args) throws IOException{
// 入力をするためには,System.inからBufferedReaderを作らなくてはいけない
BufferedReader d=new BufferedReader(new InputStreamReader(System.in));
int sum=0,num=0;
// 条件式が常に trueなので,ループの終了は break でおこなう.
while(true){
String s;
// 一行入力して文字列型変数 s に入れる
s=d.readLine();
// 整数値に変換する
try{
// この中でエラーが起きる可能性がある.
num=Integer.parseInt(s);
}
// java.lang.NumberFormatExceptionが起きた時は ここに飛ぶ
catch(java.lang.NumberFormatException e){
System.out.println("数字を入力してください");
// while文を繰り返す
continue;
}
// 負の値の時は while 文から抜ける
if(num<0) break;
sum+=num;
}
System.out.println(sum);
}
}
実行例(下線がついているのが入力)
ca20121$ java SumInput
3
soko
数字を入力してください
4
-1
7
try文は,
try ブロック catch(エラーの引数) ブロック .. catch(エラーの引数) ブロック finally ブロックという構造をしている.catchはエラーの種類に応じて複数書ける. finallyは書かなくても構わない.複数の catch を入れた例を見る.
// コマンドラインに数字列を3つ引数として与えて,足す
class SumArgs{
public static void main(String[] args){
int sum=0,num;
int i;
// 文字列の配列 argsの要素数は args.length
for(i=0;i<3;i++){
// 文字列からintへの変換
try{
num=Integer.parseInt(args[i]);
}
// args[i]の中身が
catch(java.lang.NumberFormatException e){
System.out.println("数字でない引数があったので無視します");
continue;
}
// 配列の大きさが3より小さかった場合
catch(java.lang.ArrayIndexOutOfBoundsException e){
System.out.println("3つの数字を引数に与えてください");
break;
}
// try文を抜けるときは, break, continueで抜けても実行します.
finally{
System.out.println("try文を抜けます");
}
sum=sum+num;
}
// 表示する
System.out.println("sum="+sum);
}
}
実行例
ca20121$ java SumArgs soko 4
数字でない引数があったので無視します
try文を抜けます
try文を抜けます
3つの数字を引数に与えてください
try文を抜けます
sum=4
このtry文の特徴として,tryの実行部で,他のメソッドなどを読んでいて,そ
のメソッドの中で例外が発生しても,catch部に飛んで来るということがある.
これは,大域脱出と呼ばれる機能で,C言語では setjmp, longjmpなど機種依
存のライブラリを使う必要がある.
自分で使う例外のクラスを定義して,throw文を使うと,自由に大域脱出を定
義することができるが,この授業の範囲を超えるので,例を示すに止める.
プログラム
// 自分の使う例外として, Exceptionのサブクラス MyExceptionを定義する
class MyException extends Exception{
// MyExceptionのインスタンス変数として,文字列型の変数sを宣言
String s;
// MyException のコンストラクタ
// 引数として文字列を持ち, インスタンス変数sに代入
MyException(String str){
s=str;
}
}
class ThrowException{
// 一部の例外(配列の添字チェック)を除いて,
// 内部で例外を起こす可能性のあるメソッドは, throwsで例外を書く必要がある.
static void sub() throws MyException{
// 例外を示す MyExceptionクラスのインスタンスを作成して,
// throwする.
throw new MyException("execpion in sub");
}
public static void main(String[] args){
try{
System.out.println("1");
sub();
System.out.println("2");
}
// throwを実行するとここに来る.
catch(MyException e){
// eのインスタンス変数sを表示する.
System.out.println(e.s);
}
finally{
System.out.println("3");
}
}
}
実行例
ca20121$ java ThrowException
1
execpion in sub
3