java—对未经任何引用创建的资源使用“try with resources”

6tr1vspr  于 2021-07-03  发布在  Java
关注(0)|答案(5)|浏览(431)

考虑以下情况:

try (ResultSet resultSet = DriverManager.getConnection("jdbc:...", "user", "pass")
                                      .createStatement().executeQuery(sql)) {    
                    .
                    .
                    .
}

在这种情况下,内部创建了三个资源 try 资源:a Connection ,一个 Statement ,和 ResultSet .
try块结束后,这三个资源将发生什么变化?它们是否都会关闭,即使它们没有任何参考,还是只会关闭 resultSet 关门了吗?
这个可以申报吗 AutoCloseable 在try with resource blocks中没有任何引用的资源?

cunj1qz1

cunj1qz11#

你的代码只会关闭 ResultSet ,离开 Connection 以及 Statement 打开。
在您的情况下,如果您不重用 Connection 也不是 Statement ,要全部关闭,请注意try with resources支持多个语句:

try (Connection connection = DriverManager.getConnection(...);
     Statement statement = connection.createStatement();
     ResultSet resultSet = statement.executeQuery(...)) {
    ...
}
1cosmwyk

1cosmwyk2#

它不会关闭所有这三个资源,因为您没有分别创建每个资源,每个资源后面都有分号。如果您分别创建每个资源,它将被关闭。前任:

try (
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/", "root", "password");
            Statement stmt = connection.createStatement();
            ResultSet rs = stmt.executeQuery(sql)
            ){}

这将起作用,因为try with resources语句按打开资源的相反顺序关闭资源。我们可以使用在try with resource中实现autocloseable的对象,如果它没有实现,那么它需要在final black中关闭。您可以在这里查看更多详细信息https://docs.oracle.com/javase/tutorial/essential/exceptions/tryresourceclose.html

fzwojiic

fzwojiic3#

在try with resource块中声明自动关闭资源而不引用它们安全吗?
是和否。未分配给资源变量的资源不会被此代码自动关闭。因此:
“是的”这些资源仍然可以“安全”地通过网络上的操作使用 ResultSettry 阻止。
“不”这些资源会泄漏,这很可能会导致以后的问题。
既然我把“安全”理解为这两个意思,我深思熟虑的回答是“不”,那就不安全了。
只有分配给资源变量的资源才会被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() 方法调用 close()FileWriter . 唯一可能泄漏资源的情况是 BufferedWriter 创建/构造失败。我认为只有在你运气不好的时候才有可能在那一点上得到一个oome(oome很可能会触发一个完整的垃圾回收,它将发现并关闭丢弃的资源……)

cngwdvgl

cngwdvgl4#

您也可以使用多种资源来实现这一点:

try (Connection c = DriverManager.getConnection("jdbc:...", "user", "pass");
     Statement s = c.createStatement();
     ResultSet resultSet = s.executeQuery(sql)) {
   //...
}

实现 AutoClosable 在执行 try 阻止。

ercv8c1e

ercv8c1e5#

只有 ResultSet 将关闭。如果要关闭多个资源,则需要分别声明它们:

try (Connection conn  = DriverManager.getConnection("jdbc:...", "user", "pass");
     Statement stmt = conn.createStatement();
     ResultSet resultSet = stmt.executeQuery(sql)) {    

     // do stuff...
}

相关问题