Try-With-Resources パターン
CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 62/87。
ファイルストリームやデータベース接続などのリソースを扱うときは、使い終わったら必ず閉じる必要があります。そうしないと、メモリリークが発生するおそれがあります。従来の approach では finally ブロックを使用しますが、冗長でエラーが発生しやすい方法です。
Java の try-with-resources 文は、AutoCloseable インターフェースを implements する任意の class をこの構文で使用でき、block が完了すると resources を自動的に閉じます。
// 従来のアプローチ - 冗長でリスクがある
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("file.txt"));
String line = reader.readLine();
} finally {
if (reader != null) {
reader.close(); // 例外をスローする可能性もあります!
}
}
// Try-with-resources - クリーンで安全
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
String line = reader.readLine();
} // ここで自動的にクローズされます複数のリソースは、セミコロンで区切って管理できます。リソースは宣言した順序とは逆の順序で閉じられます。
try (FileReader fr = new FileReader("input.txt");
BufferedReader br = new BufferedReader(fr)) {
// 両方のリソースを使用する
} // br が先に閉じられ、次に fr独自の自動的にクローズ可能な class を作成するには、AutoCloseable インターフェースと、その単一の close() メソッドを実装します。
public class DatabaseConnection implements AutoCloseable {
public DatabaseConnection() {
System.out.println("Connection opened");
}
@Override
public void close() {
System.out.println("Connection closed");
}
}このパターンにより、処理中に例外が発生した場合でも、リソースが常に適切に解放されることが保証されます。
チャレンジ
簡単try-with-resourcesの力を実証するリソース管理システムを構築しましょう!接続とセッションの管理をシミュレートするカスタムの自動クローズ可能な class を作成し、常に適切にクリーンアップされるようにします。
コードを3つのファイルに分けて整理します。
Connection.java: データベース接続をシミュレートする class を Create します。Connectionclass はAutoCloseableを implements する必要があります。接続名(String)用の private field、名前を受け取って[name] connection openedを出力する constructor、Executing on [name]: [sql]を出力するquery(String sql)method、そして[name] connection closedを出力する必須のclose()method が必要です。Session.java: ユーザーセッションをシミュレートする、もう1つの自動クローズ可能な class を Create します。Sessionclass もAutoCloseableを implements する必要があります。ユーザー名(String)用の private field、ユーザー名を受け取ってSession started for [username]を出力する constructor、[username] performed: [action]を出力するperformAction(String action)method、そしてSession ended for [username]を出力するclose()method を含めます。Main.java: リソース管理システムをまとめます!3つの入力、つまり接続名、ユーザー名、実行する action を受け取ります。まず、単一リソースの管理を示します。
=== Single Resource ===を出力し、try-with-resources を使って、指定された名前でConnectionを作成します。try ブロックの Inside でquery("SELECT * FROM users")を call します。ブロックが終了すると、接続は自動的に close されます。次に、Multiple リソースを示します。blank line を出力してから、
=== Multiple Resources ===を出力します。同じ名前を使うConnectionと、ユーザー名を使うSessionの both を、セミコロンで区切り、その順序で宣言して try-with-resources を使用します。try ブロックの Inside では、first に接続でquery("INSERT INTO logs")を call し、次にセッションで入力された action を指定してperformActionを call します。リソースが reverse order で close される様子を確認しましょう!
3つの入力を順番に受け取ります。接続名(String)、ユーザー名(String)、action(String)です。
try-with-resources によって、明示的な close の call や finally ブロックが不要になることに注目してください。exception が発生した場合でもリソースは確実に close され、Multiple リソースは宣言順序の reverse order で close されます!
自分で試してみよう
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String connectionName = scanner.nextLine();
String username = scanner.nextLine();
String action = scanner.nextLine();
// === Single Resource ===
// TODO: ヘッダーを出力する
// TODO: try-with-resources を使用して Connection を作成する
// TODO: Inside the try block, call query("SELECT * FROM users")
// === Multiple Resources ===
// TODO: 空行とヘッダーを出力する
// TODO: Connection と Session の両方で try-with-resources を使用する
// TODO: try ブロック内で:
// - Call query("INSERT INTO logs") on the connection
// - セッションで入力 action を使って performAction を呼び出す
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4継承
継承の基本 (extends)super キーワードメソッドのオーバーライド (@Override)コンストラクタチェーンObject クラス単一継承と多段階継承なぜ多重継承ができないのかまとめ:従業員の階層構造自分で練習してみよう: Javaオンラインコンパイラ