對Closeable和AutoCloseable的理解

目錄

Closeable和AutoCloseable的理解

背景:

一、Closeable

1.1Closeable接口源碼:

1.2使用close需要注意:

二、AutoCloseable

2.1AutoCloseable源碼

2.2.{try}-with-resources的使用注意

2.3.{try}-with-resources的解釋

2.4{try}-with-resources關鍵點


Closeable和AutoCloseable的理解

背景

在後臺開發中,規範編碼風格要求,對所有佔用的資源進行釋放,一般來說,我們進行手動的編寫close()方法進行關閉,然鵝,每次這些寫會造成代碼冗餘不優雅,JDK中對於釋放資源有Closeable和AutoCloseable可以使用,以下爲詳解。

 

一、Closeable

1.1Closeable接口源碼:

package java.io;

import java.io.IOException;

/**
 * A {@code Closeable} is a source or destination of data that can be closed.
 * The close method is invoked to release resources that the object is
 * holding (such as open files).
 *
 * @since 1.5
 */
public interface Closeable extends AutoCloseable {

    /**
     * Closes this stream and releases any system resources associated
     * with it. If the stream is already closed then invoking this
     * method has no effect.
     *
     * <p> As noted in {@link AutoCloseable#close()}, cases where the
     * close may fail require careful attention. It is strongly advised
     * to relinquish the underlying resources and to internally
     * <em>mark</em> the {@code Closeable} as closed, prior to throwing
     * the {@code IOException}.
     *
     * @throws IOException if an I/O error occurs
     */
    public void close() throws IOException;
}

 

1.2使用close需要注意:

在java.io.包下 InputStream,outputStream, Reader, Writer 等基類都實現了Closeable接口,因爲每次的IO操作結束之後都要去釋放資源。

  1. 如果在調用此方法之前 stream已經關閉 ,則方法失效;
  2. 建議先關閉內部的資源,並標記爲已關閉;
  3. 優先拋出IO異常;

二、AutoCloseable

AutoCloseable接口位於java.lang包下,從JDK1.7開始引入。

2.1AutoCloseable源碼

package java.lang;

/**
 * An object that may hold resources (such as file or socket handles)
 * until it is closed. The {@link #close()} method of an {@code AutoCloseable}
 * object is called automatically when exiting a {@code
 * try}-with-resources block for which the object has been declared in
 * the resource specification header. This construction ensures prompt
 * release, avoiding resource exhaustion exceptions and errors that
 * may otherwise occur.
 *
 * @apiNote
 * <p>It is possible, and in fact common, for a base class to
 * implement AutoCloseable even though not all of its subclasses or
 * instances will hold releasable resources.  For code that must operate
 * in complete generality, or when it is known that the {@code AutoCloseable}
 * instance requires resource release, it is recommended to use {@code
 * try}-with-resources constructions. However, when using facilities such as
 * {@link java.util.stream.Stream} that support both I/O-based and
 * non-I/O-based forms, {@code try}-with-resources blocks are in
 * general unnecessary when using non-I/O-based forms.
 *
 * @author Josh Bloch
 * @since 1.7
 */
public interface AutoCloseable {
    /**
     * Closes this resource, relinquishing any underlying resources.
     * This method is invoked automatically on objects managed by the
     * {@code try}-with-resources statement.
     *
     * <p>While this interface method is declared to throw {@code
     * Exception}, implementers are <em>strongly</em> encouraged to
     * declare concrete implementations of the {@code close} method to
     * throw more specific exceptions, or to throw no exception at all
     * if the close operation cannot fail.
     *
     * <p> Cases where the close operation may fail require careful
     * attention by implementers. It is strongly advised to relinquish
     * the underlying resources and to internally <em>mark</em> the
     * resource as closed, prior to throwing the exception. The {@code
     * close} method is unlikely to be invoked more than once and so
     * this ensures that the resources are released in a timely manner.
     * Furthermore it reduces problems that could arise when the resource
     * wraps, or is wrapped, by another resource.
     *
     * <p><em>Implementers of this interface are also strongly advised
     * to not have the {@code close} method throw {@link
     * InterruptedException}.</em>
     *
     * This exception interacts with a thread's interrupted status,
     * and runtime misbehavior is likely to occur if an {@code
     * InterruptedException} is {@linkplain Throwable#addSuppressed
     * suppressed}.
     *
     * More generally, if it would cause problems for an
     * exception to be suppressed, the {@code AutoCloseable.close}
     * method should not throw it.
     *
     * <p>Note that unlike the {@link java.io.Closeable#close close}
     * method of {@link java.io.Closeable}, this {@code close} method
     * is <em>not</em> required to be idempotent.  In other words,
     * calling this {@code close} method more than once may have some
     * visible side effect, unlike {@code Closeable.close} which is
     * required to have no effect if called more than once.
     *
     * However, implementers of this interface are strongly encouraged
     * to make their {@code close} methods idempotent.
     *
     * @throws Exception if this resource cannot be closed
     */
    void close() throws Exception;
}

 

2.2.{try}-with-resources的使用注意

在1.7之前,我們通過try{} finally{} 在finally中釋放資源。

在finally中關閉資源存在以下問題:

  • 自己要手動寫代碼做關閉的邏輯;
  • 有時候還會忘記關閉一些資源;
  • 關閉代碼的邏輯比較冗長,不應該是正常的業務邏輯需要關注的;

2.3.{try}-with-resources的解釋

對於實現AutoCloseable接口的類的實例,將其放到try後面(我們稱之爲:帶資源的try語句,源碼中的({@code{try}-with-resources)),在try結束的時候,會自動將這些資源關閉(調用close方法)。

官網解釋:

An object that may hold resources (such as file or socket handles) until it is closed. The close() method of an AutoCloseable object is called automatically when exiting a try-with-resources block for which the object has been declared in the resource specification header. This construction ensures prompt release, avoiding resource exhaustion exceptions and errors that may otherwise occur.

(一個可以保存資源(如文件或套接字句柄)直到它被關閉的對象。AutoCloseable對象的close()方法在退出資源塊時被自動調用,資源塊是在資源規範頭中聲明的對象。這種構造確保了快速釋放,避免了可能發生的資源耗盡異常和錯誤。 )

 

2.4{try}-with-resources關鍵點

帶資源的try語句的3個關鍵點:

  1. 由帶資源的try語句管理的資源必須是實現了AutoCloseable接口的類的對象。
  2. 在try代碼中聲明的資源被隱式聲明爲fianl。
  3. 通過使用分號分隔每個聲明可以管理多個資源。

 

簡單來說,實現了AutoCloseable接口的類再在執行結束後自動執行close方法來釋放資源。比如:

public class AutoCloseableTest {

    public static void main(String [] args){
        try(ConnectionLock lock = new ConnectionInnerLock()){

            //do something lock
            System.out.println("doing business...");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


interface ConnectionLock extends AutoCloseable{

    /**
     * 釋放資源
     */
    void unlock();
}

class ConnectionInnerLock implements ConnectionLock{

    /**
     * 釋放資源
     */
    @Override
    public void unlock(){

        //do release resource
        System.out.println("release resource ");
    }

    @Override
    public void close() throws Exception {
        this.unlock();
    }
}

參考:

https://docs.oracle.com/javase/8/docs/api/index.html

https://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html

https://www.jianshu.com/p/958ea3a269b4

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章