JavaSilverに向けて⑬ 例外処理
・例外とは
javaでは、コンパイル時点でエラーが発生する場合と実行中にエラーが発生する場合がある。
コンパイル時のエラーは、書き間違いなどの記述ミスや文法上の間違いがあった場合に起こる。
実行時に発生するエラーは、予期せぬ事が起こった場合に起こる。数値が入力される事を予定してプログラムを組んだにも関わらず、数値以外の値が入力された場合などが当てはまる。
Javaでは、この実行時に発生するエラーを例外が発生したという。
・例外処理
try {
//処理内容
} catch() {
//エラー発生時の処理
}
処理内容に対してでた例外をcatchして、その例外に対してプログラムを独自に記述する事ができる。
Javaはオブジェクト指向であり、例外もオブジェクトとして扱う。
Javaの例外処理には「Throwable」クラスがある。Throwableクラスのサブクラスは「Exception」クラスがあり、さらに「RuntimeException」クラスがある。
ExceptionクラスかRuntimeExceptionクラスを継承する事で独自のクラスを作成する事ができる。
例外が発生すると、tryブロックの途中であってもcatchブロックに移行する。
catchブロックは複数記述する事ができる。しかし、到達できない例外(コード)である場合は、コンパイルエラーとなる。
・finallyブロック
finallyブロックは、例外の発生に関わらず必ず実行される。
finallyブロックを複数記述するとコンパイルエラーになる。
*例外として以下の場合はfinallyブロックが実行されない。
try, catchブロックで、System.exitメソッドを呼び出してアプリケーションを強制的に終了した場合。
JVMやOSがクラッシュした場合。
・try-catch-finallyとreturn文
catchブロック内でreturn文が宣言されても、呼び出し元のメソッドに制御が戻る前にfinallyブロックに移行する。
finallyブロックが呼ばれてからreturn文により呼び出し元に制御が戻される。
・finallyブロックで変数の値を変更できるか
以下のような場合、変数valueの値が変わるだけで、戻り値の変数の値は変わらない。
public static int sample() {
int value = 0;
try {
~
} catch( ~ e) {
val = 10;
return val;
} finally {
val += 10;
}
return val;
}
Exceptionの種類
・java.io
データストリーム、直列化、ファイルシステムの入出力に関するパッケージ
ー CharConversionException
文字変換で発生する例外の基底クラス。
ー EOFException
入力の途中で予想外のファイルの終了、予想外のストリームの終了があった時の例外。
ー FileNotFoundException
指定されたパス名でファイルが開けなかった時の例外。
ー IOException
何らかの入出力に関する例外。
・java.lang
Javaプログラム言語の設計にあたる基本的なクラス
ー ArrayIndexOutOfBoundsException
不正なインデックスを使って配列がアクセスされた時に出る例外。
ー ArrayStoreException
不正な型のオブジェクトをオブジェクトの配列に格納しようとした際に出る例外。
ー ClassCastException
あるオブジェクトを継承関係にないクラスにキャストしようとした際に出る例外。
ー ClassNotFoundException
指定された名前のクラスの定義が見つからなかった場合に出る例外。
ー IllegalArgumentException
不正な引数、不適切な引数をメソッドに渡した際に出る例外。
ー IndexOutOfBoundsException
ある種のインデックス(配列、文字列など)が範囲であることを示す。
ー NegativeArraySizeException
負のサイズを持った配列をアプリケーションが作成しようとした際に出る例外。
ー NoSuchFieldException
指定された名前のフィールドがクラスにない時に出る例外。
ー NoSuchMethodException
メソッドが見つからない場合に出る例外。
ー NullPointerException
nullに対してメソッドを呼び出した際に出る例外。
・例外処理とthrows
例外処理を行わず、発生した例外をそのままスローする事ができる。
メソッド throws 例外オブジェクト {
}
Exceptionクラスを継承している例外クラスは、try-catchしているかthrows句で宣言する必要がある。
しかし、RuntimeExceptionとそのサブクラスは、非検査例外として扱われるため、try-catch, throwsする必要がない。
・ネストされたtry-catchブロック
ネストされている場合、例外を受け取るのはその例外に対応した最も近いcatchブロック。
catchブロックで処理されたら、内側から順にfinallyブロックが実行される。
・try-with-resources文
try(resource…){}
tryのブロックを抜ける時にresourceがcloseされる。finallyブロックでresourceをcloseする必要はない。
resourceが複数ある場合は「;」で区切る。
resourceのclose処理中に発生した例外は無視される。
resourceのcloseの順番は定義の逆。
protected void copy(String src, String dest) throws IOException {
try(InputStream inputStream = new FileInputStream(src); OutputStream outputStream = new FileOutputStream(dest)){
byte[] buf = new byte[100];
int n;
while((n=in.read(buf)) >= 0) {
out.write(buf, 0, n);
}
}
}
参照(https://qiita.com/NagaokaKenichi/items/124f0e14ce5dfcbd0b6b)
・例外処理とエラー
エラーは、プログラム実行中にJava仮想マシン上で異常が発生した事を指す。
エラーが起こった際には、プログラムは強制終了する。
例外は、プログラム実行中に異常な事が起こった事を指す。
*エラーの例
実行マシンのメモリ不足
ディスクに対する読み取りなどの権限問題
ネットワークに接続できなかった場合
エラーが起こった際には、対応するErrorのサブクラスのインスタンスが自動的に生成される。例外と違い、try-catch文で記述する必要はなく、throws句で宣言する必要もない。
しかし、意図的に例外処理として記述することもできる。
・StackOverflowError
public class Main {
public static void main(String[] args) {
main(args);
}
}
上記の場合、同じメソッドを呼び出し続け、領域が足らなくなる。
そのため、上記のように同じメソッドを呼び続けると、StackOverflowErrorというエラーが出て強制終了する。