Java隐含try-with-resources

我想知道以下代码是否正确使用了try-with-resources。

try (ResultSet rs = new QueryBuilder(connection, tableName(), getPaths(), searchQuery()).add(constraint).build().executeQuery()) { while (rs.next()) { beans.add(createBean(rs)); } } 

争论并不重要,唯一重要的是:

  • new QueryBuilder().build(); 返回PreparedStatement

我完全理解rs会被关闭,但PreparedStatement也会被关闭,如果是这样,出于什么原因? 因为ResultSet关闭还是因为try-with-resources?

PreparedStatement #close()将自动关闭任何关联的结果集,但反之则不正确,因为语句在结果集关闭后可重复使用。

查看ResultSet#close()的javadoc:

注意:当Statement对象关闭时,Statement对象会自动关闭,该对象会生成它

然后是Statement#close() :

注意:关闭Statement对象时,其当前ResultSet对象(如果存在)也将关闭。

这个用法看起来很糟糕我:

 ResultSet rs=conn.createStatement().executeQuery(); 

如果执行足够多次,它将泄漏所有可用游标,因为游标与Statement不与ResultSet相关联。

因此,要使用try-with-resources语句关闭底层PreparedStatement ,只需在try语句中声明它:

try-with-resources语句使用变量(称为资源)进行参数化,这些变量在执行try块之前初始化并自动关闭

从assylias看这个答案 ,在try语句中声明PreparedStatementResultSet

既然你没有寻找内存泄漏,而是资源泄漏PreparedStatement的内存最终将被收集,并且它的内存被释放,因为在执行初始化的方法后,它不再被引用,但是, Statement所持有的资源没有被关闭。

您可以在try中包含多个资源,它们都将被关闭 – 如果您希望关闭PreparedStatement ,这是必需的:

 try (PreparedStatement ps = new QueryBuilder(connection, tableName(), getPaths(), searchQuery()).add(constraint).build(); ResultSet rs = ps.executeQuery();) { while (rs.next()) { beans.add(createBean(rs)); } } 

根据这里的文档- tryResourceClose ,正如我读到的那样,它特定于declared资源。

The try-with-resources statement is a try statement that declares one or more resources.

进一步阅读你看到:

You may declare one or more resources in a try-with-resources statement. The following example retrieves the names of the files packaged in the zip file zipFileName and creates a text file that contains the names of these files:

  try ( java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName); java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset) ) { 

我建议您正确答案的问题如下:

 try{ PreparedStatement statement = new QueryBuilder(connection, tableName(), getPaths(), searchQuery()) .add(constraint).build(); ResultSet rs = statement.executeQuery()) } 

正如您所说, rs将被关闭。 这实际上意味着将在rs上调用close()方法。 因此,try-with-ressource语句在您的情况下不会明确地关闭PreparedStatement

如果它关闭,否则(在rs.close()上下文中)在不知道实现的情况下很难说;-)

编辑

正如@TheNewIdiot正确找到的那样,您的PreparedStatement将不会被关闭。