プログラミング自主 21日目 例外(Exception)/例外の処理/例外の優先順位/例外とデバッガ/finally&resource/tr
例外(Exception)
System.out.println(2/0); ->error
Javaでは、整数を0に分けることは許されず、プログラムが停止する。このように入力値を処理することできず、プログラムの実行するうちに参照しているコードに問題がある現象を例外と呼ぶ。
例外の例>
・整数を0で割り算を行った。
・配列の要素数より大きい要素数を指定してアクセスした。
・ユーザーは入力間違いを行った。(数値入力を要求しているのに、英子の入力等)
・存在しないファイルを指定し、ファイルの読み込みを行った。
・データーべースに接触が行えなかった。
・割り当てられていない記憶領域へのアクセスを行った。(不正な値のポインタを参照など)
このような状況を予測して、例外を処理することが重要である。
例外の処理
try&catch
エラーが発生する可能性があるコードはtry&catchを使用して例外処理ができる。
try{エラーが発生する可能性があるコード}
catch(例外の種類 e)
{停止されず、実行されるコード}
tryに様々なコードがあるとすれば、例外が発生したコードの下のコードは実行されない。
例外の優先順位
継承関係を考えてみると、スーパークラスであるExceptionalを使用して、全ての例外を処理することもできる。
すべての例外を Exception クラスでキャッチする場合、個々の例外に対して異なる処理を行うことはできない。以下がその例である。
また、個々の例外をキャッチすることで様々な処理ができるが、
注意点として、スーパークラス(上位クラス)の例外処理ブロックが
サブクラス(下位クラス)の例外処理ブロックよりも前に配置される必要がある。
なぜなら、すでにスーパークラスで例外が処理されているため、
サブクラスの例外処理をする理由がないためだ。
例外とデバッガ
catchのメソッドにget.Message()メソッドを呼び出すことで、例外の原因が分かる。
また、printStackTrace()を呼び出すことで、例外が発生した位置をコンソールより把握することができる。
Checked Exception(チェック例外) vs Unchecked Exception(実行時例外)
参照:Youtube '생활코딩', Java 예외 - 6. checked vs unchecked exception1
例外を二つには分ければ、Checked ExceptionとUnchecked Exceptionに分かれる。
Checked Exceptionとはコンパイラーがチェックを強制する例外である。コンパイル時に検出され、例外が処理されない場合は、コンパイルエラーが発生する。
ファイルの読み込みエラー、ネットワーク接続の問題、データベースのエラーなどが一般的なチェックエラーの例である。そのため、プログラマーは必ず明示的に例外の処理を行う必要がある。
RuntimeExceptionを継承していない例外クラスであれば、チェック例外だと考えても良い。
例>IOException、FileNotFoundException
Unchecked ExceptionとはRuntime Exceptionを継承した例外のクラスである。コンパイラがチェックを強制しない例外であるため、ヒューマンエラーが行いやすい。
Unchecked Exceptionが発生しても例外処理は強制されないため、プログラマーが適切な例外処理を行わない場合、
例外が無視されたり適切な対応が行われない場合がある。
したがって、開発者はUnchecked Exceptionに対する例外処理を慎重に考慮する必要がある。
例>ArrayIndexOutOfBoundsException、ArithmeticException
例外処理には主に二つがある。
1)try-catchで処理する。
try-catchを使用して、例外を通常の状態で戻したり、明示的にエラーが生じたことを知らせる。
2)throwsをして、例外を上位メッソドに投げる。例外処理を回避することである。
ちんと分けた場合を除外して、なるべく避けるべきな行為だ。
finally&resource
finally
は、例外の有無に関わらず必ず処理させたい場合に使う。
例えば、クラスFileWriterのように、データーをファイルにアウトプットしたり、ネットワークのように外部のリソースにアウトプットする場合はエラーが起こりやすい。
参照:youtube, '생활코딩' , Java 예외 - 7. finally와 resource 다루기
リソースに繋がった後は必ずClose(); メソッドを使用して、ファイルを閉める必要があるが、Close()
メソッドより例外が発生する可能性もある。
public class Exception;
public static void main(String[] args){
FileWriter f;
try {f=new FileWriter("data.txt");
f.write("hello");
f.close(); // ⇦ここから例外が発生し、catchに進めるとclose();が実行できない。
} catch(IOException e){
e.printStackTrace();
}
}
}
そのために活用するのはクラスfinallyのブロックである。
public class Exception;
public static void main(String[] args){
FileWriter f;
try {f=new FileWriter("data.txt");
f.write("hello");
} catch(IOException e){
e.printStackTrace();(
} finally {
f.close();
}
}
}
しかし、 try {f=new FileWriter("data.txt");よりまた例外が発生する場合、FileWriter型の変数fは値を割り当てられず、そのまま、f.closeにすすむため、また例外が生じる可能性がある。
最終的にはclose()が値がある際のみ、作動する条件文を作成する。
FileWriter f = null; (変数に値がない)
try {f=new FileWriter("data.txt");
f.write("hello");
} catch(IOException e){
e.printStackTrace(
} finally {
if(f!=null){
f.close();
}
}
}
}
最後に、もう一度、FileWriterのメソッドCloseの例外処理を行う。
try-with-resource
このように、リソースに関わるコードはfinallyを活用することもできるが、様々なコードが重なり、複雑になるため、ミスが起こりやすい。
そのため、Java 8よりはAuto ClosableというInterfaceができ、コードをとても簡単にまとめることができるようになった。Finallyとclose()が含めているため、明示的に表す必要もない。
Discussion