Java程式設計中資源物件管理的進化

chszs發表於2018-08-08
版權宣告:本文為博主chszs的原創文章,未經博主允許不得轉載。 https://blog.csdn.net/chszs/article/details/81509169

Java程式設計中資源物件管理的進化

  • 2018.8.8
  • 版權宣告:本文為博主chszs的原創文章,未經博主允許不得轉載。

使用Java開發業務時,常常需要處理資源,這是很常見的需求。

Java 7以前

在Java 7以前,處理(關閉)資源是這樣的:

public static int getAccountStatusCodeFromDataStore_traditional(String accountId) throws SQLException {
    String accountStatusCodeQuery = getAccountStatusCodeQuery(accountId);
    Statement statement = null;
    ResultSet resultSet = null;
    try {
        statement = createStatementFromConnection();
        resultSet = statement.executeQuery(accountStatusCodeQuery);
        return getAccountStatusCodeFromResultSet(resultSet);
    } finally {
        if (resultSet != null)
            resultSet.close();
        if (statement != null)
            statement.close();
    }
}

開發人員必須關閉建立的所有資源,否則會導致資源洩漏。

Java 7/8

而在Java 7中,引入了try-with-resources的新方法,可以在try-catch塊中使用的正確順序自動處理資源的關閉,比如:

public static int getAccountStatusCodeFromDataStore_java7(String accountId) throws SQLException {
    String accountStatusCodeQuery = getAccountStatusCodeQuery(accountId);
    try (Statement statement = createStatementFromConnection();
            ResultSet resultSet = statement.executeQuery(accountStatusCodeQuery)) {
        return getAccountStatusCodeFromResultSet(resultSet);
    }
}

在此示例中,可以看到程式碼更簡潔了,整體可讀性提高了,它實現了資源的自動管理。我們可以在try-with-resources語句中擁有多個資源,且多個資源的宣告之間應該用分號分隔。當這些資源在自動關閉時,也會保持宣告的反向邏輯順序依次關閉(最後宣告的資源將首先關閉)。

如果這裡要丟擲異常,try塊的異常會會壓制try-with-resources塊的異常。如果確實有需要,可以通過從try塊丟擲的異常中呼叫Throwable.getSuppressed方法來檢索被try塊抑制的異常。

另外,try-with-resources語句也可以有catch和finally塊。在宣告的資源被關閉後會執行任何catch或finally塊。

Java 9

而到了Java 9時代,對於try-with-resources的資源處理,Java 9中引入了更簡潔的版本。如果開發者已經將資源宣告為final或effective final型別,那麼可以在try-with-resources中直接使用它們而無需建立任何新變數。這使得我們可以進一步利用自動資源管理。上面的程式碼現在可使用更簡潔的try-with-resources實現,如下:

public static int getAccountStatusCodeFromDataStore_java9(String accountId) throws SQLException {
    String accountStatusCodeQuery = getAccountStatusCodeQuery(accountId);
    // 明確宣告final
    final Statement statement = createStatementFromConnection();
    // effective final
    ResultSet resultSet = statement.executeQuery(accountStatusCodeQuery);
    try (statement; resultSet) {
        return getAccountStatusCodeFromResultSet(resultSet);
    }
}

可見,程式碼的易讀性提高了。

其實大多數的資源類在背後實現了AutoCloseable或Closeable介面,因此與try-with-resources語句協同工作才實現了自動資源管理。如果我們處理的資源沒有實現AutoCloseable或Closeable介面,那麼就必須遵循傳統的方法來關閉資源。


相關文章