2013-07-22 33 views
15

我想知道下面的代碼是否正確地使用try-with-resources。Java隱式試用資源

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關閉或因爲試用資源?

回答

19

PreparedStatement#close()將自動關閉任何關聯的結果集,但相反的結果集不正確,因爲在結果集關閉後語句是可重用的。

看的ResultSet#close()的Javadoc:

注: ResultSet對象由生成它Statement對象關閉

然後Statement#close() Statement對象自動關閉:

說明:當Statement對象關閉時,其當前ResultSet對象(如果存在)也將關閉。

這種用法看起來很蹩腳的對我說:

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

如果執行足夠的時間,將泄漏所有可用遊標,因爲遊標與StatementResultSet有關。

因此關閉底層PreparedStatementtry-with-resources statement,只是try語句中聲明它:

一次嘗試與資源聲明參數與變量(被稱爲資源)的執行之前被初始化的嘗試塊和自動關閉

this answer from assylias,聲明PreparedStatement以及ResultSettry語句中。

由於您不是在尋找內存泄漏,而是資源泄漏PreparedStatement的內存將最終收集並釋放內存,因爲在初始化方法執行後不會再引用它,但是由Statement保留的資源未關閉。

2

正如你所說的,rs將被關閉。這實際上意味着將在rs上調用close()方法。所以try-with-ressource語句並不會在你的情況下明確地關閉PreparedStatement

如果它否則關閉(在rs.close()的上下文中)是種很難在不知道實現;-)

編輯

由於@TheNewIdiot正確地發現,你的PreparedStatement韓元」說不要關閉。

9

可以包括幾個資源的嘗試,他們都將被關閉 - 如果你想PreparedStatement被關閉這是必要的:

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

我不得不說(現在又會有),但我有點想避免tw o不同的聲明。 – skiwi

+0

+1你打敗了我:-) –

+0

@skiwi我實際上發現把它分成兩個可讀性更強,而不是更少。 – assylias

3

根據文檔here - 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()) 
}