亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

異常安全返回自動關閉的對象

異常安全返回自動關閉的對象

莫回無 2022-09-14 16:32:13
當您想要使用某些對象時,您應該使用試用資源。還行。但是,如果我想寫方法,那會返回呢?在創建或從某個地方接收可自動關閉的對象后,您應該在發生異常時將其關閉,如下所示:AutoClosableAutoClosable    public static AutoCloseable methodReturningAutocloseable() {        AutoCloseable autoCloseable = ... // create some AutoClosable        try {            ... // some work        }        catch (Throwable exception) {            autoCloseable.close();            throw exception;        }        return autoCloseable;    }如果你不寫塊,你會泄漏資源,該自動關閉的對象將保持不變,以防出現異常。但這還不夠,因為也可以拋出異常(根據設計)。因此,上面的代碼將轉換為try/catch// some worktry/catchautoCloseable.close()    public static AutoCloseable methodReturningAutocloseable() {        AutoCloseable autoCloseable = ... // create some autoclosable        try {            ... // some work        }        catch (Throwable exception) {            try {                autoCloseable.close();            }            catch (Throwable exceptionInClose) {                exception.addSuppressed(exceptionInClose);                throw exception;            }            throw exception;        }        return autoCloseable;    }這是很多樣板。有沒有更好的方法來在java中做到這一點?
查看完整描述

1 回答

?
尚方寶劍之說

TA貢獻1788條經驗 獲得超4個贊

有一些方法。

  • 使用“圍繞執行”成語。重新制定接口以簡化客戶端實現并消除問題。

  • 忽略問題。聽起來很愚蠢,但這通常是使用 I/O 流裝飾器包裝時發生的情況。

  • 包裝在代理中,并將其放在試用資源中。AutoCloseable

  • 寫出與資源一起嘗試使用嘗試捕獲和嘗試最終的等效項。(我不會 - 討厭。

  • 將修改后的試用資源編寫為庫功能。此代碼將成為執行周圍的客戶端。

  • 編寫異常處理舊學校風格與嘗試捕捉和嘗試最終。

編輯:我想我會重新審視答案,添加一些示例代碼來娛樂。

圍繞成語執行

簡單而最好的解決方案。不幸的是,Java庫并不經常使用它(這是一個很大的例外),并且約定也沒有很好地建立。與以往一樣,Java在沒有支持功能的情況下檢查的異常使事情變得棘手。我們不能使用,必須發明我們自己的功能接口。AccessController.doPrivilegedjava.util.function

// Like Consumer, but with an exception.

interface Use<R, EXC extends Exception> {

    void use(R resource) throws EXC;

}


public static void withThing(String name, Use<InputStream,IOException> use) throws IOException {

     try (InputStream in = new FileInputStream(name)) {

         use.use(in);

     }

}

很好,很簡單。無需擔心客戶端代碼會弄亂資源處理,因為它不會這樣做。好。


修改后的“使用資源試用”作為庫功能,作為代理實現,可在“使用資源試用”中自動關閉


它會變得丑陋。我們需要將獲取、發布和初始化作為 lambdas 傳遞。直接在此方法中創建資源將打開一個小窗口,其中意外的異常會導致泄漏。


public static InputStream newThing(String name) throws IOException {

    return returnResource(

        () -> new FileInputStream(name),

        InputStream::close,

        in -> {

            int ignore = in.read(); // some work

        }

    );

}

的一般實現將類似于下面的這個黑客。這是一個黑客,因為嘗試資源不支持這種事情,Java庫不支持檢查異常。請注意,限制為一個例外(對于未選中的例外,可以使用未選中的例外)。returnResource


interface Acquire<R, EXC extends Exception> {

    R acquire() throws EXC;

}

// Effectively the same as Use, but different.

interface Release<R, EXC extends Exception> {

    void release(R resource) throws EXC;

}


public static <R, EXC extends Exception> R returnResource(

    Acquire<R, EXC> acquire, Release<R, EXC> release, Use<R, EXC> initialize

) throws EXC {

    try (var adapter = new AutoCloseable() { // anonymous classes still define type

        private R resource = acquire.acquire();

        R get() {

            return resource;

        }

        void success() {

            resource = null;;

        }

        public void close() throws EXC {

           if (resource != null) {

               release.release(resource);

           }

        }

    }) {

        R resource = adapter.get();

        initialize.use(resource);

        adapter.success();

        return resource;

    }

}

如果我們將構建資源的參數與資源的構造分開,這可能會更干凈。


public static InputStream newThing(String name) throws IOException {

    return returnResource(

        name,

        FileInputStream::new,

        InputStream::close,

        in -> {

            int ignore = in.read(); // some work

        }

    );

}


// Like Function, but with a more descriptive name for a functional interface.

interface AcquireFrom<T, R, EXC extends Exception> {

    R acquire(T t) throws EXC;

}


public static <T, R, EXC extends Exception> R returnResource(

    T t, AcquireFrom<T, R, EXC> acquire, Release<R, EXC> release, Use<R, EXC> initialize

 ) throws EXC {

     return returnResource(() -> acquire.acquire(t), release, initialize);

 }

因此,總而言之,以下事情是痛苦的:

  • 轉讓資源所有權。將其保留在本地。

  • java.util.function不支持選中的異常。

  • Java 庫不支持執行周圍。

  • AutoCloseable::close聲明它拋出而不是成為類型的類型參數。Exception

  • 已檢查沒有總和類型的異常。

  • 一般的 Java 語言語法。


查看完整回答
反對 回復 2022-09-14
  • 1 回答
  • 0 關注
  • 102 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號