try(mc; conn;)
ここに conn も記述しているので、try から抜けるときに mc と conn の close がそれぞれ呼ばれているだけではないでしょうか。
AutoCloseableインタフェースのclose()の実装についての疑問です。
以下のようなサンプルコードがあります。
AutoCloseableインタフェースを実装した自作のMyConnectionクラスでclose()の実装を行っています。
参考書などで良く見るclose()の実装です。
オーバーライドしたclose()では、特にリソースのクローズ処理を行っていません。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
class MyConnection implements AutoCloseable{
Connection conn =null;
final String url="jdbc:mysql://localhost:3306/dbtest";
public Connection getMyConnection() {
try {
conn=DriverManager.getConnection(url,"test","pass");
return conn;
}catch(SQLException e) {
e.printStackTrace();
return conn;
}finally {
System.out.println("MyConnectionのfinallyが呼ばれた");
}
}
@Override
public void close() {
System.out.println("MyConnectionのclose()が呼ばれた");
}
}
public class TestMain {
public static void main(String[] args) {
MyConnection mc = new MyConnection();
Connection conn=mc.getMyConnection();
try(
mc;
conn;
){
System.out.println("TestMain");
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if(conn.isClosed()) {System.out.println("★connは閉じられた");}
else {System.out.println("★connは閉じられていない");}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
本来なら以下サンプルコードスニペットのような実装が必要と思っていました。
@Override
public void close() {
System.out.println("MyConnection-close()");
try {
if(conn!=null) {conn.close();
System.out.println("connは閉じられた");
}
}catch(SQLException e) {
e.printStackTrace();
}
}
MyConnectionクラスで作成したリソースでは、close()の実装に必要と思っていたコードスニペットが実装されていないためリソースはクローズされていない。
と推測しました。
そこで、TestMainクラスのfinally句で、リソースが閉じられたか?をチェックしてみました。
結果は、以下のようにクローズされているような結果になっていました。
MyConnectionのfinallyが呼ばれた
TestMain
MyConnectionのclose()が呼ばれた
★connは閉じられた
そこで、質問なのですが、
AUtoCloseableインタフェースのclose()は実装の内容に関係なく、暗黙的にリソースがクローズされるようになっているのでしょうか?
お手数おかけいたしますが、ご教授いただければ幸いです。
何卒、宜しくお願いいたします。
try(mc; conn;)
ここに conn も記述しているので、try から抜けるときに mc と conn の close がそれぞれ呼ばれているだけではないでしょうか。
@page2
Questioner@page2
Questioner@page2
Questionerはい、close()が呼ばれているのですが、close()の実装は
System.out.println();
だけで、リソースのクローズ処理は実装されていません。
あなたがクローズ処理をOverrideしているのはMyConnectionのみです.
一方でソースではMyConnection.getConnection
経由で取得したConnectionインスタンスをtry-with-resourcesで自分からクローズしてるよってことです.
現状のMyConnectionの実装はgetConnection()からConnectionインスタンスをユーザに提供する以上,そのConnectionインスタンスについてはユーザが責任を負うことになるので,カプセル化のメリットが少ないものになります.
Connectionをcloseする時に何かしたい程度なら,AutoClosableを実装したクラスを作るとか大がかりなことをしなくてもfinallyで十分です.
@page2
Questioner