🐕

プログラミング自主 21日目 例外(Exception)/例外の処理/例外の優先順位/例外とデバッガ/finally&resource/tr

2023/06/16に公開

例外(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