【コラム】
3回にわたってJava SE 7で導入される予定のクロージャについて紹介してきたが、少しずつ具体的な形が見えてきただろうか。今回はJavaのクロージャにおける例外の扱いについて紹介したい。
クロージャでは例外をスローすることもできる。そのためにはリスト1のように、throwsキーワードを使ってスローしたい例外クラスを戻り値の後に指定すればよい。
import java.io.*;
class ExceptionSample {
public static void main(String[] args) {
try {
Writer writer =
new PrintWriter(new FileWriter("sample.txt"));
// 例外付きのクロージャ
{ String => void throws IOException } write =
{ String message => writer.append(message + "\n"); };
try {
write.invoke("Good morning!");
write.invoke("Good afternoon!");
} finally {
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
このクロージャではWriterのappend()メソッドを呼び出しているが、append()はIOExceptionをスローする可能性がある。そこでthrowsでIOExceptionを指定することによって、通常のメソッドの場合と同様に例外がスローされることを明示している。
クロージャのブロックステートメント内で例外がスローされる可能性がある場合、そのクロージャの関数型は自動的にthrowsで修飾されたものになり、throwsの付かない関数型との互換性はなくなる。たとえば前述の例の場合、リスト2のようにthrowsの指定を外してしまうと、プロンプト1に示すようなコンパイルエラーになる。
{ String => void } write =
{ String message => writer.append(message + "\n"); };
ExceptionSample.java:13: 互換性のない型
検出値 : {java.lang.String => void throws java.io.IOException}
期待値 : {java.lang.String => void}
では、例外をスローするクロージャの実装はどうなっているのか見てみよう。まず、このクロージャの型を表すインタフェースjavax/lang/function/unrestricted/VO.classを逆コンパイルしてみるとリスト3のようになっており、invoke()メソッドにthrowsが指定されていること分かる。このinvoke()の実装はExceptionSample.classを逆コンパイルすれば見られるが、要約するとリスト4のような感じだ。したがってinvoke()呼び出し時にはIOExceptionをcatchしなければならない。
public interface VO {
public abstract void invoke(Object obj) throws Throwable;
}
public final void invoke(String s) throws IOException {
writer.append((new StringBuilder())
.append(s).append("\n").toString());
}
Java SE 7ではクロージャの追加に合わせて、ジェネリクスの型引数で例外のthrow宣言ができるようになるという。これを例外型引数(Exception Type Parameters)と呼び、これを利用することでスローする例外の種類を実行時に決定できるようになる。例外型引数はたとえばリスト5のように記述する。
import java.io.*;
class ExceptionSample2 {
static <throws E> void todo({ => void throws E } block) throws E {
block.invoke();
}
public static void main(String[] args) {
// 例外なしでの呼び出し
todo({ => System.out.println("Hello!"); });
try {
Writer writer =
new PrintWriter(new FileWriter("sample.txt"));
// 例外付きの呼び出し
todo({ => writer.append("Hello!"); });
} catch (IOException e) {
e.printStackTrace();
}
}
}
この例の場合、todo()メソッドには引数として何らかの例外をスローする可能性のあるクロージャを渡す。その例外の種類は例外型引数で指定されているので実行時に決まる。最初の呼び出しでは単に"Hello!"と表示するだけのクロージャなので、例外はスローされない。2番目の呼び出しではWriterのappend()を使うクロージャなので、IOExceptionがスローされる可能性がある。したがって呼出し時にはこれをcatchする必要がある。
なお、もしクロージャの実行時にスローする例外を明示的に指定したい場合にはリスト6のようにすればいいとのこと。
ExceptionSample2.<throws IOException>todo({ => writer.append("Hello!"); });
クロージャで複数の例外をスローするように宣言することも可能。それには、通常のthrows宣言と同様にスローしたい例外のクラスをコンマで区切って並べればよい。リスト7はIOExceptionとInterruptedExceptionを同時に指定した例である。これは渡されたた文字列をファイルに書き込むクロージャだが、書き込み後にThread.sleep()で100msスリープさせているため、InterruptedExceptionをスローする可能性がある。したがってInterruptedExceptionのthrows宣言を省略するとコンパイルエラーになる。
なお、catchブロックの「catch (IOException | InterruptedException e)」というのは、Java SE 7で導入される予定のマルチキャッチの機能を用いた記述。キャッチしたい例外を"|"で続けて記述することにより、ひとつのcatchブロックで複数の例外を処理することができるようになる。
import java.io.*;
class ExceptionSample3 {
public static void main(String[] args) {
// 複数の例外をスローする
{ String =>
void throws IOException, InterruptedException } write =
{ String message =>
Writer writer =
new PrintWriter(new FileWriter("sample.txt"));
writer.append(message + "\n");
Thread.sleep(100);
writer.close();
};
try {
write.invoke("Good morning!");
write.invoke("Good afternoon!");
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
例外型引数を使う場合にも複数の例外をスローするように明示的に指定することができる。この場合、のときのように呼出し側で具体的な例外のクラスを指定するが、その際にマルチキャッチのときと同様に"|"で区切って任意の例外を並べて記述する。たとえば先述のtodo()メソッドの呼び出しならばリスト8のようになる。
try {
// 複数の例外を明示的にスロー
ExceptionSample2_3.
<throws IOException | InterruptedException>todo(
{ => Writer writer =
new PrintWriter(new FileWriter("sample.txt"));
writer.append("Hello!");
Thread.sleep(100);
writer.close();
});
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
この例でtodo()に渡しているのは、リスト7と同様にIOExceptionとInterruptedExceptionの両方をスローする可能性があるクロージャである。したがってこの2つのクラスをthrowsで明示的に宣言している。
提供:マイナビ
大学・大学院・短大・専門学生向けの就職情報サイト「マイナビ2010」「マイナビ2009」に今すぐ登録しよう! 大手企業からベンチャー企業までの約13,000社の企業情報を公開、エントリーが可能です。2010年卒予定の方は「マイナビ2010」に、2009年卒予定の方は「マイナビ2009」に登録してください。
毎日コミュニケーションズはプライバシーマークを取得しています。
| 理研、脳・脊髄形成に必要な神経板湾曲の仕組みを解明 [20:16 5/25] |
| 京大、「慢性閉塞性肺疾患」患者の労作時呼吸困難は鍼治療が有効と実証 [20:08 5/25] |
| 120Hz SHVカメラ用イメージセンサーを使った撮像装置 - SHVフルスペック化へ [18:10 5/25] |
| 京大、視覚による物体認知は前頭前野からのトップダウン信号が重要と確認 [17:45 5/25] |
| 製品数の拡大だけでなくBCPの展開なども含めた総合力で事業の強化を図るTI [17:25 5/25] |
|
【ネタバレもありの徹底解明コラム】『サザエさん』タマの意外な事実 [17:30 5/27] ホビー |
|
鍼灸(しんきゅう)師が教える。オフィスで口臭予防ツボ・ベスト3 [17:00 5/27] キャリア |
|
[梶浦由記]米「アニメ・エキスポ」に2度目の参加決定 [17:00 5/27] ホビー |
|
【連載】これだけは要チェック! TOEIC(R)単語帳 第107回 今回のお題は…「chemical」 [17:00 5/27] キャリア |
|
[乃木坂46]キャプテン桜井が“ライバル”AKB総選挙予想 1位まゆゆ、2位はさしこ、3位たかみな [16:58 5/27] ホビー |
4つの診断で、自分の適性を見つめなおそう!
働くこと・挑戦し続けることへの思いを綴ったインタビュー
あなたにピッタリのアドバイスを読むことができます。
転職に必要な情報が収集できます
企業からアプローチのメッセージが届きます。