第70回 Javaの例外処理の構造(文法的なお話) その1

Javaの例外処理はかなりきっちりめにできており、
例外が起こった場合の処理を書いておかないとコンパイラさえ通らない。

なお、大きくわけて例外は、処理しなければならない例外と、処理しなくてもいい例外の2つに別けることができる。
処理しなければならない例外を処理しなければコンパイラが通らないという訳である。


今回は、処理しなければならない例外に関しての話を進めていく。
(私の確認もかねている)

例外を起こすメソッド

今、badMethodという内部で例外を起こすメソッドを考える。
これは、

private static void badMethod() throws Exception {
	throw new Exception(); 
}

このように書ける。


これをmainメソッドから呼んでいるのが次の通り

public class Hoge {

	public static void main(String[] args) {
		badMethod();
	}

	private static void badMethod() throws Exception {
		throw new Exception(); 
	}
}

この badMethodをtryしてやることで、例外を処理する。
上記のままではコンパイルが通らないのだ。

public class Hoge {

	public static void main(String[] args) {
		try {
			badMethod();
		} catch (Exception e) {
			System.out.println("例外処理った");
			e.printStackTrace();
		}
	}

	private static void badMethod() throws Exception {
		throw new Exception(); 
	}
}

結果:

例外処理った
java.lang.Exception
	at Hoge.badMethod(Hoge.java:14)
	at Hoge.main(Hoge.java:6)

e.printStackTrace() ってなに?

e.printStackTrace()とは何か気になるところだろう。
eというのはExceptionクラスのインスタンスである。
だから、

e.printStackTrace()

というのは、ExceptionのprintStackTraceメソッドを呼んでいるだけに他ならない。
このメソッドが何をしたかというと。

java.lang.Exception
	at Hoge.badMethod(Hoge.java:14)
	at Hoge.main(Hoge.java:6)

この部分を表示しており、何行目で例外が発生したのかを示している。
例外が発生したのは、badMethodの中でそれは14行目である。さらにmainメソッドの6行目にそれがthrowされているのが読み取れる。


では、なぜeにExceptionのインスタンスが入ったかと言うと次の図を見て欲しい。

badMethodの中では、

throw new Exception(); 

と書かれている。
newなので新しいインスタンスが作られているのである。
throwはそれを呼びだしもとに返しているのである(「投げている」と表現した方がすっきりする)。

この投げられたExceptionのインスタンスがtryで囲まれていると、それが、

} catch (Exception e) {

のeに入るのである。これは代入されたとも考えられる。



PerlのError.pmを用いれば、この代入されている勘がもろに味わえるだろう。

use strict;
use Error qw(:try);

try{
  die 'OH';
} otherwise {
  my $e = shift;
  print $e;
};

結果:

OH at e.pl line 5.