Checked: コンパイル時にチェックされる例外
もしあるメソッド内部のコードがchecked exceptionを投げうる場合は、そのメソッドはその例外をtry/catch
で処理するか、throws
キーワードで指定しておく必要がある. (詳細: try/catch か throws Exception か)
例えば、以下のコードを考える. このコードでは、FileReader()
を使っているが、FileReader()
はFileNotFoundException
というchecked exceptionを投げうる(throws
している)ため、このままではコンパイルしない. また、readLine()
メソッドや、close()
メソッドも使っているが、それらもIOException
を投げうる.
import java.io.*;
class Main {
public static void main(String[] args) {
FileReader file = new FileReader("C:\\test\\a.txt");
BufferedReader fileInput = new BufferedReader(file);
// Print first 3 lines of file "C:\test\a.txt"
for (int counter = 0; counter < 3; counter++)
System.out.println(fileInput.readLine());
fileInput.close();
}
}
上記のコードをコンパイルしようとすると、以下のようなエラーになる.
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code -
unreported exception java.io.FileNotFoundException; must be caught or declared to be
thrown
at Main.main(Main.java:5)
この問題を解決するためには、 throws
で例外のリストを指定するか、try/catch
を使うことである. 今回の例では、 FileNotFoundException
は IOException
のサブクラスなので、以下のようにIOException
のみを指定すれば良い.
import java.io.*;
class Main {
public static void main(String[] args) throws IOException {
FileReader file = new FileReader("C:\\test\\a.txt");
BufferedReader fileInput = new BufferedReader(file);
// Print first 3 lines of file "C:\test\a.txt"
for (int counter = 0; counter < 3; counter++)
System.out.println(fileInput.readLine());
fileInput.close();
}
}
Unchecked: コンパイル時にチェックされない例外
C++では全ての例外がuncheckedなため、コンパイラに例外処理や例外指定を要求されることはなく、その対処は書き手に委ねられている.
Javaでは、throwableなクラスの中で、Error
クラスとRuntimeException
クラス以下の例外のみunchecked exceptionで、他は全てcheckkedである.
以下のコードは、実行時にArithmeticException
を投げるが、コンパイルはできる. ArithmeticException
がunchecked exceptionであるからである.
class Main {
public static void main(String args[]) {
int x = 0;
int y = 10;
int z = y/x;
}
}
なぜchecked/uncheckedの2つのタイプを持つのか?
起こりうる例外を指定するのはメソッドのインターフェースの責務
メソッド無いうで投げられうるchecked exceptionを全て指定するのは、メソッドのインターフェースの責務であり、そのメソッドを呼び出す元は、どのような例外が投げられうるのかを知ることで、対処できる. もし全ての例外がuncheckedであれば、APIの呼び出し元にとっては大変である.
引数、返り値とならんで、インターフェース定義の一部に、例外の指定もあると考えている.
APIクライアントが処理できない/するべきではない問題のみ、unchecked exceptionを用いる
例外を指定することが良いことならば、なぜunchecked exceptionは存在するのか?Runtime Exceptionも指定すれば?と思うかもしれない.
しかし、APIの呼び出し元が処理することができなかったり、処理することが望ましくない問題に対して、unchecked exceptionを投げる.
またRuntime exceptionはどこでも起きうるため、全てに対応を入れたら、コードの可読性を下げてしまう.
RuntimeExceptionを投げるタイミング
メソッドの呼び出し方が誤っている時にRuntime Exceptionを出すのが、一つの慣習である.
単に呼び出し元での例外処理が面倒だからという理由でRuntimeExceptionを使うことは、なるべく避けたい.
例外をcheckedにすべきか?uncheckedにすべきか?
APIクライアント(メソッドの呼び出し元)が例外を処理できる/すべきケースではcheckedを、そうでない場合はuncheckedを使用するべきである.
参考: