Previous | Next | Trail Map | Writing Java Programs | 例外を使用したエラー処理


Java 例外との最初の出会い

InputFile.java:8: Warning: Exception java.io.FileNotFoundException must be caught, or it must be declared in throws clause of this method.
        fis = new FileInputStream(filename);
              ^

InputFile クラスはエラーが発生する時に例外をあげるメソッドへの呼び出しを含むので、クラスInputFile をコンパイルしようとした場合、上記のエラーメッセージに類似したメッセージに出会う。 Java 言語は、メソッドの適用範囲内であげられるすべての確認済例外をこのメソッドがキャッチするか、あるいは指定することのいずれかを要求する。 (これが実際に何を意味するかについての詳細は、次のページの Java のキャッチまたは指定の条件で説明される。) InputFile 内のメソッドのように、コンパイラがこの条件を満たさないメソッドを検出すると、上記に示すようなエラーメッセージを発行して、プログラムのコンパイルを拒否する。

詳細に InputFile を見て、起こっていることを見てみる。

InputFile クラスは FileInputStream をラップして、入力ストリーム上の現在位置から1行を読むメソッド getLine() を提供する。

    // 注:このクラスはコンパイルを通らないよう設計されている 
      orこのクラスはコンパイルとなる
import java.io.*;

class InputFile {

    FileInputStream fis;

    InputFile(String filename) {
        fis = new FileInputStream(filename);
    }

    String getLine() {
        int c;
        StringBuffer buf = new StringBuffer();

        do {
            c = fis.read();
            if (c == '¥n')             // UNIX new line
                return buf.toString();
            else if (c == '¥r') {      // Windows 95/NT new line
                c = fis.read();
                if (c == '¥n')
                    return buf.toString();
                else {
                    buf.append((char)'¥r');
                    buf.append((char)c);
                }
            } else
                buf.append((char)c);
        } while (c != -1);

        return null;
    }
}

コンパイラは,上記のコードリストの太字の行が原因で最初のエラーメッセージを出力する。 太字の行は新規の FileInputStream オブジェクトを作成して、ファイルを開くためにそれを使用する(そのファイル名は FileInputStream コンストラクタに渡される)。

それでは、 FileInputStream は指定された名前のファイルがファイルシステムに存在しない場合は、何を行うべきか? まあ、それは FileInputStream を使用しているプログラムが何を行いたいかに依存する。 FileInputStream の実装者は、ファイルが存在しない場合、InputFile クラスが何を行いたいのか分からない。 FileInputStream はプログラムを終了するべきか? 代わりのファイル名を試みるべきか? 指定された名前のファイルを作成するべきか? FileInputStream 実装者が,すべての FileInputStream のユーザに適した解を選択できる方法はない。 それで、FileInputStream 実装者は例外をあげる。 つまり、FileInputStream コンストラクタへの引数で指定された名前のファイルがファイルシステムに存在しない場合、コンストラクタは java.io.FileNotFoundException をあげる。 例外をあげることによって、 FileInputStream は呼び出しメソッドが最も適切な方法でエラーを処理することを可能にする。

コードからわかるように、InputFile クラスは FileInputStream コンストラクタが例外をあげることができる事実を完全に無視している。 しかし前に述べたように、 Java 言語は、メソッドがそのメソッドの適用範囲内であげられるすべての確認済例外をキャッチするか、あるいは指定するかのいずれかを要求する。 InputFile クラスがいずれも行わないので、コンパイラはプログラムのコンパイルを拒否して、エラーメッセージを出力する。

先に示した最初のエラーメッセージに加えて、InputFile クラスをコンパイルすると、次に示したエラーメッセージに類似したエラーメッセージが出力される。

InputFile.java:15: Warning: Exception java.io.IOException must be caught, or it must be declared in throws clause of this method.
        while ((c = fis.read()) != -1) {
                            ^

InputFile クラスの getLine() メソッドは InputFile のコンストラクタで開かれた FileInputStream から読み込みを行う。 FileInputStream の read() メソッドは、もし何かの理由でファイルから読み込むことができない場合は、 java.io.IOException をあげる。 しかしここでも、 InputFile クラスはこの例外をキャッチ、あるいは指定しようとはしない。 したがって 2 番目のエラーメッセージが出力される。

この点については、2つの選択肢がある。 InputFile クラスの適切なメソッド内で例外をキャッチするように調整するか、あるいは InputFile メソッドは例外を受けることを「避けて」、呼び出しスタック上の他のメソッドにこの例外の処理をゆだねるかです。 いずれかの方法で、InputFile クラスがコンパイルされる前に、InputFile メソッドは例外をキャッチするか指定するか、何かを行わなくてはならない。 詳しく知りたい人は、例外を指定することによって InputFile 内のバグを修正するInputFileDeclared クラスを参照のこと。

次のページでは、 Java のキャッチまたは指定の条件を詳細に記述する。 そして、その後のページではこの条件にいかに応ずるかを示す。


Previous | Next | Trail Map | Writing Java Programs | 例外を使用したエラー処理