練習問題のような,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);
}
}
実行例(下線がついているのが入力)
dell.tanaka.ecc.u-tokyo.ac.jp% java SumInput
3
2
-1
5
これで,数でないものを代入すると,次のように例外が表示されてプログラム
の実行を中断する.
dell.tanaka.ecc.u-tokyo.ac.jp% 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);
}
}
実行例(下線がついているのが入力)
dell.tanaka.ecc.u-tokyo.ac.jp% 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);
}
}
実行例
dell.tanaka.ecc.u-tokyo.ac.jp% 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を宣言 public 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"); } } } 実行例 dell.tanaka.ecc.u-tokyo.ac.jp% java ThrowException 1 execpion in sub 3