プログラムを作成するときは,処理がうまくいかない場合のことを考えておかなくてはならない。たとえばフロッピーディスクやハードディスクのデータを読み書きするときには,「もしフロッピーがセットされていなかったら」とか「存在するはずのファイルがなかったら」などと,正常に実行できないときのことを考えなければいけない。うまくいかないときの対処がコード化されているプログラムが良いプログラムだということになる。どこで誰が使うかわからないプログラムだといろいろな障害を想定しておかなければならない。
いつもそんな風に,うまくいかないときのことを考えてプログラムを組んでいると,プログラマは何をするときでも,うまくいかないことを前提に物事を考えるようになるのではないか。「XXをしてうまくいかない場合は,○○をしよう。」などと,ついつい次の手を私も考えてしまう。とりあえず,やってみてダメだったら,そのときに考えようなどという風に楽観的にはなれない。これはプログラマの習慣なのだろうか。読者のみなさんはどうですか? うまくいかない場合のことをついつい考えてはしまいませんか。
そんなうまくいかなかったときのことを,Javeではtry ~ catch構文を使って例外処理として記述することができる。
---------------------------------------------------------- int num1 =100; int num2 =0; num1 /=num2; ----------------------------------------------------------たとえば,上記のようにゼロで除算を行うと
---------------------------------------------------------- java.lang.ArithmeticException: / by zero ----------------------------------------------------------という算術計算の例外が発生する。もちろん,プログラマがわざと変数num2に0を代入して除算を行うことはありえないが,二つの引数を受け取り,除算を行うプログラムではどうだろう。
---------------------------------------------------------- public static void main(String[] args) { int num1 ; int num2 ; try{ num1 = Integer.parseInt(args[0]); num2 = Integer.parseInt(args[1]); num1 /=num2; }catch(ArithmeticException e){ System.err.println("算術計算で例外発生"+e); } finally { System.err.println("ここで終了処理をする"); } } ----------------------------------------------------------引数として与えられた文字列をInteger.parseIntで整数として解釈し,除算している。引数が100と0だった場合には,ArithmeticExceptionが発生する。それをJavaではcatch文で捕らえることができるのである。
ちなみにEclipseで引数を設定するには,実行メニューから実行を選び,引き数タブで次の画像のように指定する。
引数を受け取るようにするだけで,他にもいろいろなエラーが想定できるようになる。引数を100とAにすると,Aは数値に変換できないのでnum2 = Integer.parseInt(args[1])で例外NumberFormatExceptionが発生する。また,引数の指定をうっかり忘れると,例外ArrayIndexOutOfBoundsExceptionが発生する。それらに対応するには,catch文をずらずらと並べることになる。
---------------------------------------------------------- try{ num1 = Integer.parseInt(args[0]); num2 = Integer.parseInt(args[1]); num1 /=num2; }catch(ArrayIndexOutOfBoundsException e){ System.err.println("引数は二つ必要です"); }catch(NumberFormatException e){ System.err.println("引数が数値ではありません"); }catch(ArithmeticException e){ System.err.println("0で除算はできません"); } finally { System.err.println("ここで終了処理をする"); } ----------------------------------------------------------finally以降には,例外が発生してもしなくても実行する処理を記述する。たとえば,データベースへの接続の切断処理などである。
もちろん,このように引数を受け取る処理では,引数の数や値をチェックしてから除算を行う方が論理的にもスッキリするのでtry ~ catch構文で例外処理を行う必要はない。try ~ catch構文でキャッチしなくてはいけないのは「チェックされる例外」,つまり,キャッチしないとコンパイル・エラーになる例外である。でも,もっともいけないのは事前にチェックもせず,例外処理もしないことである。
プログラム実行中に使用可能なメモリがなくなったらどうしようとか,うまく処理できないときのことばかりをアレコレ考えていると,うつうつとした気分に浸り込んでいきますので,ときには「それは想定外です」とシレッと答えることも必要かもしれませんね