Ch6. 例外処理
マルチキャッチ
catchする例外クラスを複数並べて記述できる。 ただし、並べて書く際は継承関係のある例外クラスを記述できない。
public class ExceptionSample { public static void main(String[] args){ try{ throw new SubSubException(); }catch (Exception | SubSubException e){ //Types in multi-catch must be disjoint: 'SubSubException' is a subclass of 'java.lang.Exception System.out.println("Exception"); e = null; //Types in multi-catch must be disjoint: 'SubSubException' is a subclass of 'java.lang.Exception }catch (Throwable e){ e = null; } } } class SubException extends Exception{ } class SubSubException extends SubException{ }
また(意図は不明だが)マルチキャッチでキャッチした参照変数でだけ、final
状態となり変数の上書きが禁じられる。
rethrow
(Java SE6までは)throwsで明示した例外クラスを一度catchしてから再度rethrowする場合にcatch節にその例外クラスを設定する必要があった(つまり上位クラスの例外クラスではrethrowできなかった)。
具体的には以下のようなことになる。
public class ExceptionThrowsSample { public static void main(String[] args) throws MySubException{ new ExceptionThrowsSample().OriginalMethod(); } void OriginalMethod() throws MySubException{ try{ System.out.println(""); throw new MySubException(); }catch (MyException e){ //上位クラスでCatchしている。 throw e; } } } class MyException extends Exception{ } class MySubException extends MyException{ }
オーバーライドしたメソッドのthrows
オーバーライドしたメソッドでは、必ず親クラスと同じthrows
を設定しないといけないわけではない。
throwsを設定しないことも可能で、その場合オーバーラードしたメソッドを呼び出すときは例外処理が不要になる。
ただし、throwsを設定する場合は下記の例外しかthrows出来ない。 * 親クラスのthrowsで設定した例外クラスのサブクラス * RuntimeExceptionのそのサブクラス
import java.io.EOFException; import java.io.IOException; import java.sql.SQLException; class ParentalClass{ public void method() throws IOException{ } } public class OverrideThrows extends ParentalClass{ public static void main(String[] args){ OverrideThrows obj = new OverrideThrows(); obj.method(); ParentalClass obj2 = new OverrideThrows(); obj2.method();//'Unhandled exception: java.io.IOException' } public void method(){ } } class ChildClass extends OverrideThrows{ public void method() throws SQLException {//'method()' in 'ChildClass' clashes with 'method()' in 'OverrideThrows'; overridden method does not throw 'java.sql.SQLException' } } class ChildClass2 extends ParentalClass{ public void method() throws EOFException { } } class ChildClass3 extends ParentalClass{ public void method() throws SQLException { //'method()' in 'ChildClass3' clashes with 'method()' in 'ParentalClass'; overridden method does not throw 'java.sql.SQLException' } }
try-with-resources
今までfinalブロックに書いていた(DBコネクションなどの)リソースの終了処理を勝手にやってくれる仕組み。 tryの括弧の中にブロックが終わるときに終了したいリソースを書いておく。
import javax.swing.plaf.basic.BasicInternalFrameTitlePane; import java.io.Closeable; public class WithResources { public static void main(String[] args){ try(DbConnectionA a = new DbConnectionA(); DbConnectionB b = new DbConnectionB()){ System.out.println("end of try block"); }finally { System.out.println("finally Block"); } } } class DbConnectionA implements AutoCloseable{ public void close() { System.out.println("CloseA"); } } class DbConnectionB implements Closeable { public void close() { System.out.println("CloseB"); } } //end of try block //CloseB //CloseA //finally Block
抑制された例外
try-with-resourcesを使う場面だと「tryの中でも、closeの中でも例外が発生する」ということが起こりうる。 この場合、closeの中で発生された例外は「抑制された」例外として扱われ、catch節のエラー変数では(getSuppressedメソッドを利用しないと)確認することが出来ない。
getSuppressed
メソッドを使うと、発生した全てのエラーがthrowable
クラスの配列として返却されるのでcloseメソッドで発生した分を含めて全て確認することが出来る。
また、エラーオブジェクトに任意の例外を追加するメソッドも提供されている。
import java.io.Closeable; import java.util.Arrays; public class WithResources { public static void main(String[] args){ try(DbConnectionA a = new DbConnectionA(); DbConnectionB b = new DbConnectionB()){ System.out.println("end of try block"); throw new ArrayIndexOutOfBoundsException(); }catch(Throwable e){ e.addSuppressed(new StackOverflowError()); System.out.println(e); Arrays.stream(e.getSuppressed()).forEach(System.out::println); } finally { System.out.println("finally Block"); } } } class DbConnectionA implements AutoCloseable{ public void close() { System.out.println("CloseA"); throw new RuntimeException(); } } class DbConnectionB implements Closeable { public void close() { System.out.println("CloseB"); throw new ArrayStoreException(); } } //end of try block //CloseB //CloseA //java.lang.ArrayIndexOutOfBoundsException //java.lang.ArrayStoreException //java.lang.RuntimeException //java.lang.StackOverflowError //finally Block
アサーション
JVMの実行時オプションに-ea
を渡すと利用できる。
アサーションの式がfalseを返した場合、指定したメッセージを表示することが出来る。
-ea
オプションを指定しなければこの行は無視してくれるため、例えfailしても実行時に警告等は出ない。
public class AssertionSample { public static void main(String[] args){ int variable = 100; assert variable < 99 : "variable is : " + variable;//'Exception in thread "main" java.lang.AssertionError: variable is : 100' } }