[Java] 基礎的な例外処理について

### はじめに
Javaの学習のまとめです
今回は例外に絞って投稿しています。

### かなりオススメします

https://www.youtube.com/channel/UC57H40XcMcL4Lbp_Uq2MVaQ

とてもわかりやすいし、説明がすんなり入ってきます。
なぜ使うのか・いつ使うのかも含めて丁寧に説明してくれているのでJava学習をはじめたばかりの方はぜひ！
わかりやすいように構成が考えられているようで、その時その時に必要な情報を出してくれるのでパンクしないで済みます。
また、オブジェクト指向についても解説してくれていますので曖昧な方もぜひ！

### 例外
実行時に発生するエラーのこと
例外処理を行わないとプログラムにエラーが出た箇所で止まってしまい（異常終了し）、最後まで実行されない
→これだと困るので例外処理が必要になる

##### 何が起きているのか
例外が発生すると例外クラスのオブジェクトが**自動生成**される
Javaには発生するエラーごとに例外クラスが存在していて、エラーが発生するとそこからオブジェクトを自動で生成して表示してくれる

##### 大事な例外クラス
豆知識：全ての例外クラスは`throwableクラス`を継承して作られている

<dl>
  <dt>Errorクラス</dt>
  <dd>システムが原因で発生するエラーをまとめたクラス（メモリ不足など）</dd>
  <dt>Exceptionクラス</dt>
  <dd>プログラム自体が原因で発生するエラーをまとめたクラス（ファイルが見つかりませんエラーなど）</dd>
  <dt>（Exceptionクラスを継承した）RuntimeExceptionクラス</dt>
  <dd>プログラムのどこでも発生しうるエラーをまとめたクラス（0で割り算できないよエラーなど）</dd>
</dl>

##### 例外処理が必須の例外クラス（無いとコンパイルエラーになる）
Exceptionクラス（RuntimeExceptionクラスは**除く**)
例）ファイルの取得をするときなどには例外処理をしないとコンパイルエラーになってしまう

Errorクラスに関しては、メモリ不足などのプログラムでは防ぎようがないエラーなので例外処理をしなくても大丈夫

RuntimeExceptionクラスに関しては任意
割り算をするたびに「0で割れないよエラー」の例外処理を書いていくのは大変なので、プログラムを作る際に気をつけましょうってことになっている（無くてもコンパイルエラーにはならない）

### 書き方
例外処理を書く = try-catchブロックを書く
例外クラスを使用するには`import 例外クラス名;`が必要

基本構文
```java
try {
  [通常の処理]
} catch(例外クラス オブジェクト名) {
  [例外発生時の処理]
  // 複数書くことが出来る
} catch(例外クラス オブジェクト名) {
  [例外発生時の処理]
} finally {
  [後処理]
}
```

##### 実際の動き
```java
try {
  int a = Integer.parseInt(args[0]);
  System.out.println("a / b =" + (a / b));
} catch(ArrayIndexOutOfBoundsExecption e) {
  [例外発生時の処理]
  // 複数書くことが出来る
} catch(Exception e) {
  [例外発生時の処理]
} finally {
  System.out.println("プログラムを終了します");
}
```
- 正常時
```java
try {
  int a = Integer.parseInt(args[0]);
  System.out.println("a / b =" + (a / b));
} /* catch(ArrayIndexOutOfBoundsExecption e) {
  [例外発生時の処理]
} catch(Exception e) {
  [例外発生時の処理]
} */ finally {
  System.out.println("プログラムを終了します");
}
```
catch文は実行されない

- 例外発生（引数がなかった場合）
```java
try {
  int a = Integer.parseInt(args[0]);
  // System.out.println("a / b =" + (a / b)); 
} catch(ArrayIndexOutOfBoundsExecption e) {
  [例外発生時の処理]
} catch(Exception e) {
  [例外発生時の処理]
} finally {
  System.out.println("プログラムを終了します");
}
```
argsの時点でcatch文に飛びその後のtry文は実行されない

##### 注意点
catch文を複数書く時はサブクラスの例外クラスから記述！（上の場合Exceptionクラスがスーパークラス）
理由：サブクラスのオブジェクトはスーパークラスに自動で型変換されてしまう
→Excptionクラスが上にあると全てここでキャッチされてしまい、ArrayIndexOutOfBoundsExcpetionはどんなときでも実行されなくなってしまう

### throwとthrows
例外を意図的に発生させる際に使用する

throw 例外オブジェクト(例外クラスから出来たオブジェクト)：例外を強制的に**発生させる**
throws　例外クラス：メソッドがその例外を発生することを**宣言する**

##### よく使うとき
Exceptionクラスを継承した独自の例外クラスを作成したとき
処理が失敗したときに`throw new 独自の例外クラス`として例外を発生させるときに使用する

##### 使い方パターン1
メソッド内でtry-catchを書くパターン
```java
void write() {
  try {
  [if文などで例外が発生した処理と仮定]
  // IOexception e = new IOException();
  // throw e;  の略↓↓
  throw new Exception();
  // ↑で例外を発生させて↓でcatchする
  } catch(IOException e) {
          ︙
  } 
}
```


##### 使い方パターン2
メソッドの呼び出し側でtry-catchを書いてもらうパターン
```java
void write() throws IOException {
             ︙
  throw new IOException();
             ︙
}
```
`throws 例外クラス名`があるおかげでtry-catch文書かなくてもコンパイルエラーにならない
javaが用意しているメソッドによく`throw　new 例外クラス();`が使われているので、呼び出す側でメソッドを使う際にtry-catch文で書けば例外を発生させてくれる

throw:処理の流れで書くことが出来るキーワード
throws:メソッドの定義のところに書くキーワード（「発生させる可能性がありますよ」のとき、throwとセット？）
メソッドの中で複数の例外を発生させる可能性がある場合は、throwsの後に例外クラスを`,`で複数指定できる

```java
public void write() throws IOException {
 throw new IOException();
}
```

### 最後に
Railsでは例外処理に全く触れていなかったので戸惑っていますが、使っていくうちに慣れていきたいです！

閲覧いただきありがとうございました！