第九章 
 〜基本編〜
 例外
 例外って何?
   例えば道ばたを歩いてたです。そうすると前方5m先に千円札が落ちていたです。
  その千円札が、欲しいがままに走ったのです。このとき考えてもいないことが起きた
  のです。それは・・・マンホールにふたが無かったです。結局、マンホールから出てき
  たときには千円札は、無かったという話です。
   このように考えてもいなかったことは、いつ発生するか分からないです。だから
  事前に何か対処をしておかなければいけないのです。これを例外処理とJavaで
  は呼ぶです。

  書式:try{
      処理
     }catch(どのような例外か){
      例外処理
     }finally{
      例外が発生しても必ず行われる処理
     }

     補足:finallyから後は、書かなくてもいいです。
     catch()の中のカッコには具体的に例外のクラス名と変数名が入るです
     catch(例外のクラス名 変数名) ← こんな感じですね。
     例外のクラス名というのは、例外の名前だと思ってくれればいいです。

  これを最初の説明にあてはめて例外処理をすると・・・
   1: 千円札を発見
   2: try{
   3:  //何かあったら困るのでtryの中に記入
   4:  千円札を取りにいく
   5:  マンホールにふたが無い・・・
   6: }catch(マンホールにふたが無い!){
   7:  マンホールにふたが無いので、よける
   8: }finally{
   9:  親切なのでマンホールにふたをつける
  10: }
  11: 千円札ゲット♪(親切だけど交番には届けない・・・

  ちなみに、今までのやり方だと・・・
   1: 千円札を発見
   2: 千円札を取りにいく
   3: マンホールにふたが無い・・・ ← ここで、処理が停止する。千円札取得不能
   4: 千円札ゲット♪

  次に具体的に、プログラムで発生する例外とはどんなものがあるかと言うですと
  1 誤った入力をしてしまった。
  2 配列の要素数を超える場所にアクセスしてしまった。
  3 ファイル入出力で正しく入出力できなかった。
  などがあげられると思うです〜。特に1、2での例外はおきてしまった人はいるかもしれ
  ないです。ちなみに例外が発生したらその場でプログラムが終了して
  変なメッセージが出てきたはずです。
  次のプログラムを見てほしいです〜
サンプルプログラム5_3
   1:
   2:
   3:
   4:
   5:
   6:
   7:
   8:
   9:
   10:
   11:
   12:
   13:
   14:
   15:
   16:
   17:
   18:
   19:
   20:
   21:
import java.io.*;

class Rei5_3{
    public static void main(String[] args) throws IOException{
        BufferedReader br = new 
            BufferedReader(new InputStreamReader(System.in));

        System.out.print("1つめの値を入力:");
        String str1 = br.readLine();

        System.out.print("2つめの値を入力:");
        String str2 = br.readLine();
        
        int num1 = Integer.parseInt(str1);
        int num2 = Integer.parseInt(str2);
        
        num1 = num1 + num2;
        
        System.out.println("2つの値を足すと:" + num1 + "になるですね!");
    }
}

   これは、第5章でやったときの2つの値を入力して足し算するプログラムですね!
  ここで、2つの値を入力するときに、整数以外の値を入れてみるとどうなるですかね?
  先ほど言ったことがおこるはずです。例外(謎のメッセージ)が出て止まるはずです。
  なぜそのようなことがおきたかと言うと14行目で、文字列型を整数型に変換しようと
  しているのに、変換しようとしている値の変換後が整数にならないからです〜
  例えば1.5を入力すると、それは整数じゃないですね(文字や文字列も駄目です)
  つまりエラー(例外)が発生するです。そして例外が発生したプログラムは強制終了
  されるです。もちろん強制終了したので足し算はできないです・・・
  これはマンホールに落ちて、千円札を手に入れると言うという使命!?ができなかった
  ことと同じですね!

   今度は、例外処理を使って書いてみるです
サンプルプログラム9_1
   1:
   2:
   3:
   4:
   5:
   6:
   7:
   8:
   9:
   10:
   11:
   12:
   13:
   14:
   15:
   16:
   17:
   18:
   19:
   20:
   21:
   22:
   23:
   24:
   25:
   26:
   27:
   28:
import java.io.*;

class Rei9_1{
    public static void main(String[] args) throws IOException{
        try{
            BufferedReader br = new 
                BufferedReader(new InputStreamReader(System.in));

            System.out.print("1つめの値を入力:");
            String str1 = br.readLine();

            System.out.print("2つめの値を入力:");
            String str2 = br.readLine();

            int num1 = Integer.parseInt(str1);
            int num2 = Integer.parseInt(str2);
            
            num1 = num1 + num2;
            System.out.println("2つの値を足すと:" + num1 + "になるですね!");
        }
        catch(NumberFormatException nfe){
            System.out.println("整数を入力してください。");
        }
        finally{
            System.out.println("プログラムは終了されました♪");
        }
    }
}

   さっきと同じように整数以外を入力すると、今度は変なメッセージは出てこなくな
  ると思うですね!これは、例外処理をしっかりと書いたからです。
  int num1 = Integer.parseInt(str1);を処理したときに、もしstr1に整数以外の値に
  なる文字列が入っていたら、ここで例外が発生して、
  catch(NumberFormatException nfe)を実行するです。
  NumberFormatExceptionは、変なメッセージの中にあったと思うです。
  あの変な文字列は、例外メッセージを実は出していたのです〜
  このNumberFormatExceptionは、値をフォーマットするとき(別の値にするとき)に
  正しく変換されないときに発生するです。
   もしどんな例外が発生するか分からないような場合、catchのカッコの中には、
  Exceptionを入れるといいです〜。これを使えばどんな例外も対処してくれるです〜
  でもやっぱり例外処理は1つ1つ書いたほうがいいのでExceptionは例外の名前を
  調べるときに使えばいいと思うです。
  具体的にはこのようにやるです〜
  catch(Exception e){
    System.out.println("例外クラス名:" + e);
  }
  eの中には、例外名が入ってくるので、その値を出力してあげれば例外名が分かるです。
  1つ1つ書く方法は次にやるです。

 複数の例外処理を書く
  try{
   処理
  }
  catch(例外1){
   例外1の例外処理
  }
  catch(例外2){
   例外2の例外処理
  }
  finally{
   例外が発生しても必ず行われる処理
  }

  catch()を何個も書いてあげるだけでいいですね!
  何度も言う(打つ)ですけどfinallyは書かなくても結構ですよ。
 必ず行う処理がある場合は書いたほうが無難ですね。
 では、この例外処理を使ったプログラムを作ってみたいと思うです。
 ちなみにこのプログラムはサンプルプログラム9_1をちょっと改造したものです。
サンプルプログラム9_2
   1:
   2:
   3:
   4:
   5:
   6:
   7:
   8:
   9:
   10:
   11:
   12:
   13:
   14:
   15:
   16:
   17:
   18:
   19:
   20:
   21:
   22:
   23:
   24:
   25:
   26:
   27:
   28:
   29:
   30:
   31:
import java.io.*;

class Rei9_2{
    public static void main(String[] args){
        try{
            BufferedReader br = new 
                BufferedReader(new InputStreamReader(System.in));

            System.out.print("1つめの値を入力:");
            String str1 = br.readLine();

            System.out.print("2つめの値を入力:");
            String str2 = br.readLine();

            int num1 = Integer.parseInt(str1);
            int num2 = Integer.parseInt(str2);
            
            num1 = num1 + num2;
            System.out.println("2つの値を足すと:" + num1 + "になるですね!");
        }
        catch(NumberFormatException nfe){
            System.out.println("整数を入力してください。");
        }
        catch(IOException ioe){
            System.out.println("入出力エラー。");
        }
        finally{
            System.out.println("プログラムは終了されました♪");
        }
    }
}

   このプログラムにはcatch()が二つついてるですね!
  それだけでなくIOExceptionがmain()メソッドの右から消えてるはずです。
  消えていると言うか正確には、catch()のところに移されたって感じです。
  結果的には、throwsで例外に備えるのとcatch()で例外に備えるとの違いだけでどちら
  も例外処理を行ってくれるです〜厳密には違ってくるですが、似たようなものだと思っ
  ていいと思うです〜
   性格には、try〜catch()は例外処理をするもの。tryの中で発生した例外を
  catch()で受け取る場合。
  throwsは、このプログラムでは、例外が発生するかもしれないという予告を書くです
  これはtryに、似てるですね!しかしtryと違ってその例外が発生するかもしれない
  メソッド内では、例外処理を書くことができないです。
   本当は、このthrowsとthrowを組み合わせて、try〜catch()内で例外処理をする
  という例外処理の内部について触れたいところですが・・・
  まだクラスについて学んでないので、できないです・・・
  もしやるとしたら、おまけのところにこの例外処理の続きを書いておくです〜
  まだ先になっちゃうかも知れないですが、とりあえず例外処理についてはここで
  お終いです〜。
  でも例外処理は大切なので、知っておいて損はないですね!
  知って損するものもないかも・・・

  最後によく出てくる(使う)例外クラス名(例外名)を書いておくです〜
例外クラス名 説明
ArrayIndexOutOfBoundsException 配列の要素数を超えた値を入れたとき発生
NumberFormatException 正しく値が正しく変換されないとき発生
IOException 入出力エラーが発生したとき発生
NullPointerException 何も割り当てられていないオブジェクトを指したとき発生
ArithmeticException 0で割ってしまったとき発生
Exception どんな例外でもいいから発生したとき発生

   テラオメがJavaをやっていてIOExceptionは、発生したとこがないです・・・
  今回のポイント
  @ 例外処理をするには、try〜catchを使う。
  A 何の例外か分からないときは、Exception 変数名で取得した変数名を表示する
  B 例外がtryの中で発生したら強制的にcatch内に移動する。
  C finallyは、書かなくてもいい
  D 複数の例外処理を書くことができる。Exceptionだけにして、すべての例外に
    備えて、エラーメッセージを1つだけにすることもできる。

  TOPに戻る     Java講座に戻る