第71回 Javaの例外処理の構造(文法的なお話) その2
それでは、try{ } catch { } の構造を使うと、
どのようにプログラムが流れていくのか見てみよう。
public class Hoge { public static void main(String[] args) { try { badMethod(); System.out.println("例外起こらないでー"); } catch (Exception e) { System.out.println("例外処理った"); e.printStackTrace(); } System.out.println("ここまでこれるかな"); } private static void badMethod() throws Exception { throw new Exception(); } }
結果:
例外処理った java.lang.Exception at Hoge.badMethod(Hoge.java:16) at Hoge.main(Hoge.java:6) ここまでこれるかな
おわかりだろうか?
System.out.println("例外起こらないでー");
の部分が実行されていないのである。
tryの中で例外が発生すると(今回は、badMethod();の部分)それより以下の行は処理されない(すっとばされるのである)。
finally
ちなみにfinallyというものが存在する。
catchは例外が起こったときに処理される部分であるが、
finallyは、例外が起こったときも起こらなかったときも、最後に必ず実行されるのである。
それでは、例外が起こった場合からみてみよう。
public class Hoge { public static void main(String[] args) { try { badMethod(); System.out.println("例外起こらないでー"); } catch (Exception e) { System.out.println("例外処理った"); e.printStackTrace(); } finally { System.out.println("Hey!! みんなのfinally"); } System.out.println("ここまでこれるかな"); } private static void badMethod() throws Exception { throw new Exception(); } }
結果:
例外処理った java.lang.Exception at Hoge.badMethod(Hoge.java:18) at Hoge.main(Hoge.java:6) Hey!! みんなのfinally ここまでこれるかな
では、次に例外が起こらなかった場合である。
public class Hoge { public static void main(String[] args) { try { badMethod(); System.out.println("例外起こらないでー"); } catch (Exception e) { System.out.println("例外処理った"); e.printStackTrace(); } finally { System.out.println("Hey!! みんなのfinally"); } System.out.println("ここまでこれるかな"); } private static void badMethod() throws Exception { // throw new Exception(); コメントアウトした } }
結果:
例外起こらないでー Hey!! みんなのfinally ここまでこれるかな
このように、どちらの場合もfinallyの中は実行されているのがわかる。
finallyは必要なのか?
それでは、
try{ A } catch { B } finally { F } D
と書くのも、
try { A } catch { B } F D
と書くのも同じように思えるが、
次のような違いがあるようだ。
なるほど。例外をさらに上に投げるときにfinallyは使えるらしい。
やってみよう。
public class Hoge { public static void main(String[] args) { try { giveUp(); System.out.println("main() : 例外起こらないでー"); } catch (Exception e) { System.out.println("main() : 例外処理った"); e.printStackTrace(); } } private static void badMethod() throws Exception { throw new Exception(); } private static void giveUp() throws Exception { try{ badMethod(); } catch (Exception e) { System.out.println("giveUp() : catchした!"); throw e; } finally { System.out.println("giveUp() : finally!!"); } System.out.println("giveUp() : 例外処理後"); } }
新たに、giveUpメソッドを用意し、
そのgiveUpメソッドがbadMethodを呼んでいるが、自分では結局処理せず、
呼び出し元に任せている(throwしている)。
結果:
giveUp() : catchした! giveUp() : finally!! main() : 例外処理った java.lang.Exception at Hoge.badMethod(Hoge.java:15) at Hoge.giveUp(Hoge.java:20) at Hoge.main(Hoge.java:6)
たしかに、呼び出し元に投げているにもかかわらず、
投げる前に、finallyが実行されている。
では、Error.pmはどうかというと、
use strict; use Error qw(:try); sub bad_sub { die 'OH'; } sub give_up { try { bad_sub(); } otherwise { my $e = shift; print 'give_up() : catchした', "\n"; die $e; } finally { print 'geve_up() : finally', "\n"; }; } try { give_up(); } otherwise { my $e = shift; print 'main() : 例外処理った', "\n"; print $e; };
結果:
give_up() : catchした geve_up() : finally main() : 例外処理った OH at e.pl line 5.
確かに、Error.pmもそのような挙動をする。
ちなみに、上に投げる方法は、tryを書かずに
use strict; use Error qw(:try); sub bad_sub { die 'OH'; } sub give_up { bad_sub(); print 'ここは通らない', "\n"; } try { give_up(); } otherwise { my $e = shift; print 'main() : 例外処理った', "\n"; print $e; };
結果:
main() : 例外処理った OH at e.pl line 5.
このようにも書けるが、これはあまりよいとは思えないような気がする。
が、どうなんだろう.....