try-with-resources 文は、1 つ以上のリソースを宣言する try 文である。
ここで言うリソースはプログラムで読み込みや書き込みなどを行った後に、閉じなければならないオブジェクトを指す。
try()の()の中に使用するオブジェクトを宣言することで書くことができる。
書き方の例として以下、オラクルのドキュメントの例を引用。
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
ちなみにオブジェクトは複数宣言可能みたいで、宣言する際は;で区切ることが必要である。
try文の()の中にリソース宣言して処理を書いていくことができ、処理終了後はリソースは自動的に閉じられる。
例を見ただけではなんなので、通常のtry文と比較してみた。
以下は、5分に1回の頻度でソーラン節のコピペが書き込まれたテキストファイルを作成するジョブの一部である。
ファイルにコピペを書き込む処理を通常try文とtry-with-resourcesで書いてみた。
通常のtry文の場合
String SORANBUSHI_LYRIC = "ヤーレンソーランソーランソーランソーランソーラン (ハイハイ)wwwwwwwwwwwww\r\n"
+ "にしん来たかと 鴎に問えば わたしゃ立つ鳥 波に聞け チョイwwwwwwwwwww\r\n" + "ヤサ エーエンヤーサーノドッコイショ (ハードッコイショドッコイショ)\r\n"
+ "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwww\r\n" + "ヤーレンソーランソーランソーランソーランソーラン (ハイハイ)wwwwwwwwwwwww\r\n"
+ "沖の鴎に 潮どき問えば わたしゃ立つ鳥 波に聞け チョイwwwwwwwwwwwwwwwwww\r\n" + "ヤサ エーエンヤーサーノ ドッコイショ (ハードッコイショドッコイショ)\r\n"
+ "wwwwwwwwwwwwwwwwwwwwwwwwww\r\n" + "ヤーレンソーランソーランソーランソーランソーラン (ハイハイ)wwwwwwwwwwwww\r\n"
+ "男度胸なら 五尺のからだ どんと乗り出せ 波の上 チョイwwwwwwwwwww\r\n" + "ヤサ エーエンヤーサーノ ドッコイショ (ハードッコイショドッコイショ)\r\n"
+ "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwww\r\n" + "ヤーレンソーランソーランソーランソーランソーラン (ハイハイ)wwwwwwwwwwwwwwwww\r\n"
+ "躍る銀鱗 鴎の唄に お浜大漁の 陽がのぼる チョイwwwwwwww\r\n" + "ヤサ エーエンヤーサーノ ドッコイショ (ハードッコイショドッコイショ)\r\n"
+ "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww";
// 途中処理省略
// fileNumberにはファイル作成された数だけ通し番号が入る
File soranFile = new File("C:\\Users\\User\\Desktop\\ソーラン節歌詞\\soranBushi_" + fileNumber + ".txt");
/** 通常のtry catchで書いた場合*/
try {
FileWriter filewriter = new FileWriter(soranFile);
try {
filewriter.write(SORANBUSHI_LYRIC);
} catch (IOException e) {
System.out.println(e);
} finally {
try {
if (filewriter != null) {
filewriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("ソーラン節作成完了");
}
特徴として
・close()を記述しなくてもコンパイルエラーにはならないので、リソース開放漏れの危険性がある。
・try句とfinally句の両方で同じリソースを指し示すことが必要なので、変数はtry-catch-finallyの外側で宣言する。
・close()でIOExceptionの可能性があるため、finally句の中でさらにtry-catchのネストが必要。
・tryブロックとfinallyブロックの両方で例外が発生した場合、finally句で発生した例外をスローする。try文から発生した例外は抑制されるっぽい。
try-with-resourceの場合
String SORANBUSHI_LYRIC = "ヤーレンソーランソーランソーランソーランソーラン (ハイハイ)wwwwwwwwwwwww\r\n"
+ "にしん来たかと 鴎に問えば わたしゃ立つ鳥 波に聞け チョイwwwwwwwwwww\r\n" + "ヤサ エーエンヤーサーノドッコイショ (ハードッコイショドッコイショ)\r\n"
+ "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwww\r\n" + "ヤーレンソーランソーランソーランソーランソーラン (ハイハイ)wwwwwwwwwwwww\r\n"
+ "沖の鴎に 潮どき問えば わたしゃ立つ鳥 波に聞け チョイwwwwwwwwwwwwwwwwww\r\n" + "ヤサ エーエンヤーサーノ ドッコイショ (ハードッコイショドッコイショ)\r\n"
+ "wwwwwwwwwwwwwwwwwwwwwwwwww\r\n" + "ヤーレンソーランソーランソーランソーランソーラン (ハイハイ)wwwwwwwwwwwww\r\n"
+ "男度胸なら 五尺のからだ どんと乗り出せ 波の上 チョイwwwwwwwwwww\r\n" + "ヤサ エーエンヤーサーノ ドッコイショ (ハードッコイショドッコイショ)\r\n"
+ "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwww\r\n" + "ヤーレンソーランソーランソーランソーランソーラン (ハイハイ)wwwwwwwwwwwwwwwww\r\n"
+ "躍る銀鱗 鴎の唄に お浜大漁の 陽がのぼる チョイwwwwwwww\r\n" + "ヤサ エーエンヤーサーノ ドッコイショ (ハードッコイショドッコイショ)\r\n"
+ "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww";
// 途中処理省略
// fileNumberにはファイル作成された数だけ通し番号が入る
File soranFile = new File("C:\\Users\\User\\Desktop\\ソーラン節歌詞\\soranBushi_" + fileNumber + ".txt");
/** try catch with resourceで書いた場合*/
try(FileWriter filewriter = new FileWriter(soranFile);) {
filewriter.write(SORANBUSHI_LYRIC);
System.out.println("ソーラン節作成完了");
} catch(IOException e) {
System.out.println(e);
}
特徴として
・基本的にリソースは自動で解放
・try文が正常に終了したかに例外が発生したかに関わらず、リソースは閉じられる
・tryブロックとtry-with-resourcesブロックの両方から例外がスローされた場合、tryブロックからスローされた例外をスローする。try-with-resourcesブロックからスローされた例外は抑制されるっぽい。
try-with-resourcesのほうが自動で閉じてくれるし、finally句のネストがないので個人的に読みやくて良いと思う。