对没有任何参考创建的资源使用“尝试资源”

Moh*_*dam 7 java try-with-resources autocloseable

考虑以下情况:

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

这是在资源内部创建了三个资源的情况try: a Connection、 aStatement和 a ResultSet

try 块结束后这三个资源会发生什么变化?他们会全部关闭,即使他们没有任何提及它们,还是只会resultSet关闭?

AutoCloseable在尝试使用资源块时,在没有任何引用的情况下声明资源是否安全?

Mur*_*nik 8

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

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

     // do stuff...
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*n C 6

在尝试使用资源块时,在没有任何引用的情况下声明 AutoCloseable 资源是否安全?

是和否。那些未分配给资源变量的资源不会被此代码自动关闭。所以:

  • “是”这些资源仍然可以通过块ResultSet内的操作“安全”使用try
  • “不”这些资源会泄漏,这很可能在以后引起问题。

因为我理解“安全”是指双方的这些东西,我认为答案是“否”,它是不是安全。

try-with-resources 将自动关闭的唯一资源是分配给资源变量的资源。所以正确的写法是:

try (Connection connection = DriverManager.getConnection(...);
     Statement statement = connection.createStatement();
     ResultSet resultSet = statement.executeQuery(sql)) {
    // ...   
}
Run Code Online (Sandbox Code Playgroud)

请注意,资源变量会按照与它们声明相反的顺序自动关闭。


请注意,您通常可以侥幸逃脱。例如:

try (BufferedWriter bw = new BufferedWriter(new FileWriter(...)) {
    // ...   
}
Run Code Online (Sandbox Code Playgroud)

除非在极不寻常的情况下,否则可能没问题。当bw被自动关闭,其close()方法调用close()FileWriter。这可能会泄漏资源的唯一情况是BufferedWriter创建/构造失败。我认为这只有在您不幸获得 OOME 时才有可能。(并且 OOME 很可能会触发完整的垃圾收集,无论如何都会找到并关闭丢弃的资源......)


f1s*_*1sh 5

您也可以使用多个资源来做到这一点:

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

AutoClosable执行该try块后,所有实现该接口的变量都将关闭。