練習問題のような,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 7try文は,
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