使用 "try with resources" 来创建没有任何引用的资源
Using "try with resources" for resources created without any reference
考虑以下情况:
try (ResultSet resultSet = DriverManager.getConnection("jdbc:...", "user", "pass")
.createStatement().executeQuery(sql)) {
.
.
.
}
这是在 try
个资源中创建了三个资源的情况:一个 Connection
、一个 Statement
和一个 ResultSet
。
try块结束后这三个资源会发生什么?它们会全部关闭吗,即使它们没有任何引用,还是只会关闭 resultSet
?
在尝试使用资源块时声明 AutoCloseable
资源而不引用它们是否安全?
只有ResultSet
会被关闭。如果要关闭多个资源,需要单独声明:
try (Connection conn = DriverManager.getConnection("jdbc:...", "user", "pass");
Statement stmt = conn.createStatement();
ResultSet resultSet = stmt.executeQuery(sql)) {
// do stuff...
}
您也可以使用多种资源来做到这一点:
try (Connection c = DriverManager.getConnection("jdbc:...", "user", "pass");
Statement s = c.createStatement();
ResultSet resultSet = s.executeQuery(sql)) {
//...
}
所有实现 AutoClosable
接口的变量在 try
块执行后关闭。
您的代码只会关闭 ResultSet
,而 Connection
和 Statement
打开。
在你的情况下,如果你不重用 Connection
或 Statement
,要关闭它们,请注意 try-with-resources 支持多个语句:
try (Connection connection = DriverManager.getConnection(...);
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(...)) {
...
}
Is this safe to declare AutoCloseable resources without any reference to them in try with resource blocks?
是也不是。那些没有分配给资源变量的资源不会被这段代码自动关闭。因此:
- “是”这些资源仍然可以“安全”地通过在
try
块中对 ResultSet
的操作使用。
- “不”那些资源会泄漏,这很容易在以后引起问题。
由于我将“安全”解释为两者,我考虑过的答案是“不”,它不安全。
唯一会被 try-with-resources 自动关闭的资源是分配给资源变量的资源。所以正确的写法是:
try (Connection connection = DriverManager.getConnection(...);
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql)) {
// ...
}
请注意,资源变量的自动关闭顺序与它们声明的顺序相反。
请注意,您通常可以侥幸逃脱。例如:
try (BufferedWriter bw = new BufferedWriter(new FileWriter(...)) {
// ...
}
除非在极不寻常的情况下,否则很可能没问题。当 bw
自动关闭时,它的 close()
方法调用 FileWriter
上的 close()
。这可能会泄漏资源的唯一情况是 BufferedWriter
创建/构造失败。我认为只有在您不幸获得 OOME 时才有可能。 (而且 OOME 很可能会触发一个完整的垃圾收集,无论如何都会找到并关闭丢弃的资源......)
它不会关闭所有三个资源,因为您没有分别创建每个资源后跟分号。如果您单独创建每个资源,它将被关闭。
例如:
try (
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/", "root", "password");
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql)
){}
这会起作用,因为 try-with-resources 语句会以与打开资源相反的顺序关闭资源。
我们可以使用实现 AutoCloseable 的对象来尝试使用资源,如果它没有实现,那么它需要在最终的黑色中关闭。
您可以在此处查看更多详细信息 https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
考虑以下情况:
try (ResultSet resultSet = DriverManager.getConnection("jdbc:...", "user", "pass")
.createStatement().executeQuery(sql)) {
.
.
.
}
这是在 try
个资源中创建了三个资源的情况:一个 Connection
、一个 Statement
和一个 ResultSet
。
try块结束后这三个资源会发生什么?它们会全部关闭吗,即使它们没有任何引用,还是只会关闭 resultSet
?
在尝试使用资源块时声明 AutoCloseable
资源而不引用它们是否安全?
只有ResultSet
会被关闭。如果要关闭多个资源,需要单独声明:
try (Connection conn = DriverManager.getConnection("jdbc:...", "user", "pass");
Statement stmt = conn.createStatement();
ResultSet resultSet = stmt.executeQuery(sql)) {
// do stuff...
}
您也可以使用多种资源来做到这一点:
try (Connection c = DriverManager.getConnection("jdbc:...", "user", "pass");
Statement s = c.createStatement();
ResultSet resultSet = s.executeQuery(sql)) {
//...
}
所有实现 AutoClosable
接口的变量在 try
块执行后关闭。
您的代码只会关闭 ResultSet
,而 Connection
和 Statement
打开。
在你的情况下,如果你不重用 Connection
或 Statement
,要关闭它们,请注意 try-with-resources 支持多个语句:
try (Connection connection = DriverManager.getConnection(...);
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(...)) {
...
}
Is this safe to declare AutoCloseable resources without any reference to them in try with resource blocks?
是也不是。那些没有分配给资源变量的资源不会被这段代码自动关闭。因此:
- “是”这些资源仍然可以“安全”地通过在
try
块中对ResultSet
的操作使用。 - “不”那些资源会泄漏,这很容易在以后引起问题。
由于我将“安全”解释为两者,我考虑过的答案是“不”,它不安全。
唯一会被 try-with-resources 自动关闭的资源是分配给资源变量的资源。所以正确的写法是:
try (Connection connection = DriverManager.getConnection(...);
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql)) {
// ...
}
请注意,资源变量的自动关闭顺序与它们声明的顺序相反。
请注意,您通常可以侥幸逃脱。例如:
try (BufferedWriter bw = new BufferedWriter(new FileWriter(...)) {
// ...
}
除非在极不寻常的情况下,否则很可能没问题。当 bw
自动关闭时,它的 close()
方法调用 FileWriter
上的 close()
。这可能会泄漏资源的唯一情况是 BufferedWriter
创建/构造失败。我认为只有在您不幸获得 OOME 时才有可能。 (而且 OOME 很可能会触发一个完整的垃圾收集,无论如何都会找到并关闭丢弃的资源......)
它不会关闭所有三个资源,因为您没有分别创建每个资源后跟分号。如果您单独创建每个资源,它将被关闭。 例如:
try (
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/", "root", "password");
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql)
){}
这会起作用,因为 try-with-resources 语句会以与打开资源相反的顺序关闭资源。 我们可以使用实现 AutoCloseable 的对象来尝试使用资源,如果它没有实现,那么它需要在最终的黑色中关闭。 您可以在此处查看更多详细信息 https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html