当サイトは、アフィリエイト広告を利用しています
javaの例外処理における「throw」と「throws」について 基本的なところをまとておく
javaの例外処理については下記の書籍が参考になります
javaには検査例外と実行時例外がある。
例外処理はこのうちを検査例外が発生したときの処理をコーディングする。
例外が発生する可能性があるメソッドではそのメソッドにおいて
か決めて対応をしておく必要がある。 実装としてはを
意図的に例外を発生させる機能。
例外的状況が発生したどうかはJVMが監視していて、
JVMが例外的状況を検知すると処理をcatchブロックに移す。
この例外を監視しているJVMに対して、意図的に「Exception」が発生したと通知するのが
throw命令。
例外を発生させたい場所で実行する
private static void doError() {try {throw new Exception("error");} catch(Exception e) {e.printStackTrace();}}}
プログラムに例外が生じた際に、呼び出し元に例外処理を投げる機能
例外をthrowsするメソッドに記述することで例外が発生した場合
処理が呼出し元のcatch句に移る。
※throwsはネストさせることもできるが最上位のところでは
try~catchを書いて、例外を捕捉する必要がある。
import java.util.*;public class Main {// 呼出し元public static void main(String[] args) {try {doError();} catch (Exception e) {e.printStackTrace();}}// 実行側private static void doError() throws Exception {throw new Exception("error!!");}}
Java throwsとは|throwsとthrowの違いも紹介
例外処理のパターンをいくつか実装してみる
呼出し元ではなく実行メソッド内で例外を捕捉するパターン。
import java.util.*;public class Main {// 呼出し元public static void main(String[] args) {doError();}// 実行メソッドprivate static void doError() {try {//例外を発生させるthrow new Exception("error!!");} catch(Exception e) {// 例外を捕捉//ログ出力e.printStackTrace();}}}
実行メソッドではなく呼出し元で例外を捕捉するパターン。
import java.util.*;public class Main {// 呼出し元public static void main(String[] args) {try {doError();} catch (Exception e) {//実行側の例外を捕捉して処理するe.printStackTrace();}}// 実行側private static void doError() throws Exception {//例外を発生させる//メソッドにthrowsがあるため例外を呼び出し元に投げるthrow new Exception("error!!");}}
throwsではなくtry~catchでも呼び出し元に投げることができる
NullPointerExceptionが発生するパターンを実装してみる
import java.util.*;public class Main {//呼出し元public static void main(String[] args) {try {doError();System.out.print("処理は継続する");} catch (Exception e) {e.printStackTrace();}}//実行側private static void doError() {try {//例外を発生させるthrow new NullPointerException ("ヌルぽ");} catch(Exception e) {//try句で発生したエラーをそのまま呼出し元に投げるthrow e;}}}
Exceptionを発生させる場合はthrowsが必要
import java.util.*;public class Main {//呼出し元public static void main(String[] args) {try {doError();System.out.print("処理は継続する");} catch (Exception e) {e.printStackTrace();}}//実行側private static void doError() throws Exception{try {//例外を発生させるthrow new Exception ("エクセプション");} catch(Exception e) {//try句で発生したエラーをそのまま呼出し元に投げるthrow e;}}}
例外処理がcatch句で適切にcatchされなかった場合はRuntimeErrorとなり
強制終了する。
import java.util.*;public class Main {//呼出し元public static void main(String[] args) {try {doError();//発生させた例外でない例外のみcatch} catch (IndexOutOfBoundsException e) {System.out.print(e.getMessage());e.printStackTrace();}}//実行側private static void doError(){try {//例外を発生させるthrow new NullPointerException ("ヌルぽ");} catch(Exception e) {//try句で発生したエラーをそのまま呼出し元に投げるthrow e;}}}
このような場合はNullPointerExceptionがcatchできないため
強制終了する。下記のように書いたりしてcatch漏れがないようにする。
//呼出し元public static void main(String[] args) {try {doError();//発生させた例外でない例外のみcatch} catch (IndexOutOfBoundsException e) {System.out.print(e.getMessage());e.printStackTrace();} catch (NullPointerException e) {System.out.print(e.getMessage());e.printStackTrace();}}
または
//呼出し元public static void main(String[] args) {try {doError();//発生させた例外でない例外のみcatch} catch (IndexOutOfBoundsException | NullPointerException e) {System.out.print(e.getMessage());e.printStackTrace();}}
例外が発生したことをなかったことにしてハンドリングしないことを例外を握りつぶすという。
例外処理はcatch処理をした場所で伝播が止まってしまう性質のため発生する。
※処理した例外はそこで処理したのでもう上へは連携されないこと
適切に処理しないと エラーを握りつぶしてしまうケースがある。
実行メソッドのcatch句での例外処理はログ出力しかしていない。
呼出し元は実行メソッドのcatch句の処理が完了した後、順位実行される。
import java.util.*;public class Main {// 呼出し元public static void main(String[] args) {doError();System.out.print("例外あるけど完了した");}// 実行メソッドprivate static void doError() {try {//例外を発生させるthrow new Exception("error!!");} catch(Exception e) {// 例外を捕捉//ログ出力e.printStackTrace();}}}// 実行結果// 例外あるけど完了した
実際ログを見るとエラーは発生しているがユーザーはログなど
基本見ないので例外は発生していることに気づかないため
例外がつぶされていることになる。
※まだログ出力処理があればいいがないと完全に闇に葬られることになる...
java.lang.Exception: error!!at Main.doError(Main.java:14)at Main.main(Main.java:6)
catch句で例外が発生した場合や、正しく処理しなかった場合に
例外原因が握りつぶされてなくなってしまうパターン。
import java.util.*;public class Main {/*** 例外をcatchしStackTraceを表示するメソッド* @param args*/public static void main(String[] args) {try {doMethod();} catch (Exception e) {e.printStackTrace();}}/*** catch句で例外をthrowするメソッド* @throws Exception*/private static void doMethod() throws Exception {try {throw new Exception("throw in try");} catch(Exception e) {//catch内で例外を発生させるthrow new Exception("throw in catch");}}}
実行すると
java.lang.Exception: throw in catchat Main.doMethod(Main.java:24)at Main.main(Main.java:11)
tyr内のerror情報が握りつぶされてなくなっている。
### 対応
addSuppressedを使って例外を追加することができる
import java.util.*;public class Main {/*** 例外をcatchしStackTraceを表示するメソッド* @param args*/public static void main(String[] args) {try {doMethod();} catch (Exception e) {e.printStackTrace();}}/*** catch句で例外をthrowするメソッド* @throws Exception*/private static void doMethod() throws Exception {try {throw new Exception("throw in try");} catch(Exception expInTry) {Exception expInCatch = new Exception("throw in catch");expInCatch.addSuppressed(expInTry);throw expInCatch;}}}
実行すると
java.lang.Exception: throw in catchat Main.doMethod(Main.java:24)at Main.main(Main.java:11)Suppressed: java.lang.Exception: throw in tryat Main.doMethod(Main.java:22)... 1 more
try内のerror情報もlogに出力できる