例外クラス
前節で見たように、Javaで用意されているメソッドで発生する可能性があるものは、ライブラリに説明が載せられているので、その例外クラス名を使用して例外処理を記述できます。例外処理はそれ以外にも、自分で例外クラスを作って、発生(スロー)させることもできます。
例外クラスを作成するには次のように記述します。
例外クラス定義の書式 |
---|
class 例外クラス名 extends Exception{ … } |
自分で作った例外クラスは自分でスローしなくてはなりません。例外をスローするには次のように記述します。
例外クラススローの書式 |
---|
throw 例外オブジェクト; |
ここで、先回作成したBusクラスを修正しましょう。今までは、乗車や降車をするときに走っていないかどうかなどを調べ、異常がある場合はその旨のメッセージを返すように作ってきました。それを例外処理に書き換えましょう。
○ ファイル
次のようにファイルを作成してください。
ファイル名 | WarningException.java |
---|
○ プログラム
例外を表すクラスを作成しましょう。Exceptionクラスを継承した次のようなクラスを作成してください。
WarningException.java
- public class WarningException extends Exception{
- public WarningException(String error){
- super(error);
- }
- }
○ 解説
1行目では、スーパークラスにExceptionクラスを指定しています。それにより、今回作成したWarningExceptionクラスは、スローしてキャッチすることができるようになります。例外を表すクラスは多くの場合~Exceptionのように名前を付けます。
2~4行目では、コンストラクターを定義しています。このコンストラクターはインスタンス生成時にスーパークラスであるExceptionクラスのコンストラクターを呼び出しています。引数として受け取ったエラーメッセージをさらに引数として渡しています。これによりgetMessageメソッドで、引数で指定したエラーメッセージが参照できるようになります。
○ プログラム
次にBusクラスを変更しましょう。次のように修正してください。
Bus.java
- public class Bus extends Car{
- //フィールド
- private int salesAmount; //運賃
- private int passengerNumber; //乗客人数
- //コンストラクター
- public Bus(){
- this(100);
- }
- public Bus(double gas){
- super(gas);
- this.salesAmount = 0;
- this.passengerNumber = 0;
- }
- //メソッド
- //乗車させるメソッド
- public void rideToBus(int fare) throws WarningException{
- //走行中かどうか
- if(this.getSpeed() != 0){
- throw new WarningException("停車してください。");
- }
- //満席かどうか
- if(this.passengerNumber >= 50){
- throw new WarningException("満席のため、乗車できません。");
- }
- //料金と、乗車人数を加算
- this.salesAmount += fare;
- this.passengerNumber++;
- }
- //降車させるメソッド
- public void getOffBus() throws WarningException{
- //走行中かどうか
- if(this.getSpeed() != 0){
- throw new WarningException("停車してください。");
- }
- //乗客がいるかどうか
- if(this.passengerNumber == 0){
- throw new WarningException("乗客はいません。");
- }
- //乗車人数を減算
- this.passengerNumber--;
- }
○ 解説
19、36行目では、処理の中でエラーが発生した場合は文字列を返す仕組みから例外をスローする仕組みに変更するため、戻すデータがなくなりました。そのため、戻り値の型をstringからvoidに変更しています。また、メソッドの処理内でWarningExceptionがスローされる可能性があるため、throws文を指定して、呼び出し側で処理をさせるようにしています。
22、27、39、44行目では、エラーが発生した場合にその時のエラーメッセージをreturn文で返していましたが、throw文を使って例外をスローさせるように変更しました。
○ ファイル
BusTest.javaをコピーして、次のようにファイルを作成してください。
ファイル名 | BusTest2.java |
---|
○ プログラム
次のように修正してください。
BusTest2.java
- import java.io.*;
- public class BusTest2{
- //車の状態を表示するメソッド
- public static void showData(Bus bus){
- System.out.println("スピード:" + bus.getSpeed() + "km");
- System.out.println("ガソリン:" + bus.getGas() + "L");
- System.out.println("売上金額:" + bus.getSalesAmount() + "円");
- System.out.println("乗車人数:" + bus.getPassengerNumber() + "人");
- }
- public static void main(String[] args){
- //インスタンスを生成する
- Bus bus = new Bus(150);
- //現在の状態を表示する
- showData(bus);
- //キーボード入力の準備をする
- BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
- while(true){
- try{
- //操作を入力
- System.out.print("1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:");
- String inputdata = br.readLine();
- //操作によって分岐する
- switch (inputdata){
- case "1":
- //加速する
- bus.speedUp(5);
- showData(bus);
- break;
- case "2":
- //減速する
- bus.speedDown(5);
- showData(bus);
- break;
- case "3":
- //給油する
- bus.setGas(80);
- showData(bus);
- break;
- case "7":
- //乗車する
- bus.rideToBus(200);
- showData(bus);
- break;
- case "8":
- //降車する
- bus.getOffBus();
- showData(bus);
- break;
- case "9":
- //プログラムを終了する
- return;
- }
- }catch(WarningException e){
- System.out.println(e.getMessage());
- }catch(Exception e){
- System.out.println("エラーが発生しました。");
- }
- }
- }
- }
○ コンパイルと実行
C:¥work>javac BusTest2.java
C:¥work>java BusTest2
スピード:0km
ガソリン:150.0L
売上金額:0円
乗車人数:0人
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:1
スピード:5km
ガソリン:149.5L
売上金額:0円
乗車人数:0人
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:7
停車してください。
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:2
スピード:0km
ガソリン:149.5L
売上金額:0円
乗車人数:0人
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:7
スピード:0km
ガソリン:149.5L
売上金額:200円
乗車人数:1人
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:1
スピード:5km
ガソリン:149.0L
売上金額:200円
乗車人数:1人
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:8
停車してください。
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:2
スピード:0km
ガソリン:149.0L
売上金額:200円
乗車人数:1人
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:8
スピード:0km
ガソリン:149.0L
売上金額:200円
乗車人数:0人
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:8
乗客はいません。
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:9
C:¥work>
○ 解説
23~63行目では、try~catch文が記述されています。47、52行目で、バスオブジェクトのメソッドが呼び出されると、状態によって例外(WarningException)がスローされてきます。その場合は、59行目でキャッチされ、60行目の処理が行われます。61行目はWarningException以外がtry文の中でスローされたときにキャッチされます。
catch文は複数指定することができます。try文でスローされた例外オブジェクトに応じてキャッチされます。それぞれのcatch文が上から順に評価されていきます。そのため、Exception型のcatchは最後に指定しないとエラーとなります。上の方にExeption型の指定をすると必ずそこでキャッチされ、下に指定したcatch文は使われないからです。