【Java 基本】 Checked Exception と Unchecked Exception について


## Checked: コンパイル時にチェックされる例外

もしあるメソッド内部のコードがchecked exceptionを投げうる場合は、そのメソッドはその例外を`try/catch`で処理するか、`throws`キーワードで指定しておく必要がある. (詳細: [try/catch か throws Exception か](http://qiita.com/shunsuke227ono/items/18059198777812e446b4))

例えば、以下のコードを考える. このコードでは、`FileReader()`を使っているが、`FileReader()`は`FileNotFoundException`というchecked exceptionを投げうる(`throws`している)ため、このままではコンパイルしない. また、`readLine()`メソッドや、`close()`メソッドも使っているが、それらも`IOException` を投げうる.

```.java
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`のみを指定すれば良い.

```.java
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であるからである.

```.java
class Main {
   public static void main(String args[]) {
      int x = 0;
      int y = 10;
      int z = y/x;
  }
}
```

## なぜchecked/uncheckedの２つのタイプを持つのか？ 

### 起こりうる例外を指定するのはメソッドのインターフェースの責務

メソッド無いうで投げられうる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を使用するべきである.


***

参考: 
* [Checked vs Unchecked Exceptions in Java](http://www.geeksforgeeks.org/checked-vs-unchecked-exceptions-in-java/)
* [Unchecked Exceptions — The Controversy](http://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html)