摘抄002 - Java中使用的try-with-resource機制(語法糖)來省略掉在finally中的try-catch代碼 -使用IOUtils.closeQuietly(stream)優雅關閉輸入流或輸出流


簡介+優勢分析

  1. try-with-resource借鑒鏈接(建議先看看,內容十分詳實,我做了一點點補充) https://www.cnblogs.com/itZhy/p/7636615.html
  2. IOUtils出處 https://blog.csdn.net/zmx729618/article/details/51888938/

舉個小栗子

pom簡單依賴

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>

運行1

public static void main(String[] args) {
    try (FileInputStream inputStream = new FileInputStream(new File("test.txt"))) {
        // 讀取到控制台
        System.out.println(inputStream.read());
        // 關閉輸入流  , 該方法需要上面的pom依賴
        IOUtils.closeQuietly( inputStream );
    } catch (IOException e) {
        throw new RuntimeException(e.getMessage(), e);
    }
}

結果1

Exception in thread "main" java.lang.RuntimeException: test.txt (系統找不到指定的文件。)
	at Main.main(Main.java:16)
Caused by: java.io.FileNotFoundException: test.txt (系統找不到指定的文件。)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.<init>(FileInputStream.java:138)
	at Main.main(Main.java:10)

: 可以發現 IOUtils.closeQuietly( inputStream ); 關閉流錯誤的信息沒有往外拋出來.這就是因為closeQuietly方法進行了空指針判斷! 不是異常抑制!

public static void closeQuietly(Closeable closeable) {
        try {
            if (closeable != null) {
                closeable.close();
            }
        } catch (IOException var2) {
            ;
        }

    }

同時存在異常抑制

看一眼反編譯后的代碼
看一眼反編譯后的代碼

public class Main {
    public Main() {
    }

    public static void main(String[] args) {
        try {
            FileInputStream inputStream = new FileInputStream(new File("test.txt"));
            Throwable var2 = null;

            try {
                System.out.println(inputStream.read());
                IOUtils.closeQuietly(inputStream);
            } catch (Throwable var12) {
                var2 = var12;
                throw var12;
            } finally {

                if (inputStream != null) {
                    if (var2 != null) {
                        try {
                            inputStream.close();
                        } catch (Throwable var11) {
                            var2.addSuppressed(var11);
                        }
                    } else {
                        inputStream.close();
                    }
                }

            }

        } catch (IOException var14) {
            throw new RuntimeException(var14.getMessage(), var14);
        }
    }
}

通過反編譯的代碼,大家可能注意到代碼中有一處對異常的特殊處理:

var2.addSuppressed(var11);
  • 這是try-with-resource語法涉及的另外一個知識點,叫做異常抑制。當對外部資源進行處理(例如讀或寫)時,如果遭遇了異常,且在隨后的關閉外部資源過程中,又遭遇了異常,那么你catch到的將會是對外部資源進行處理時遭遇的異常,關閉資源時遭遇的異常將被“抑制”但不是丟棄,通過異常的getSuppressed方法,可以提取出被抑制的異常。
  • try-with-resource時,如果對外部資源的處理和對外部資源的關閉均遭遇了異常,“關閉異常”將被抑制,“處理異常”將被拋出,但“關閉異常”並沒有丟失,而是存放在“處理異常”的被抑制的異常列表中。

釋放異常抑制

加點pom

 <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>
        <!-- log -->
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.21</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.21</version>
        </dependency>

加點代碼, 使用e.getSuppressed(); 獲取到被壓抑的沒能拋出的異常

@Slf4j
public class Main {
    public static void main(String[] args) {
        try (FileInputStream inputStream = new FileInputStream(new File("test.txt"))) {
            // 讀取到控制台
            System.out.println(inputStream.read());
            // 關閉輸入流
            IOUtils.closeQuietly( inputStream );
        } catch (IOException e) {
            Throwable[] suppressed = e.getSuppressed();
            for (Throwable throwable : suppressed) {
                log.error("", throwable);
            }
            throw new RuntimeException(e.getMessage(), e);
        }
    }
}

造一組樣例

對外部資源的處理和對外部資源的關閉均遭遇了異常, 太難了, 造不出來.....................
如果你可以的, 麻煩在下面貼一下`英雄帖`!

注意編譯版本的問題, 至少需要JDK5, 請在pom中指定jdk編譯版本

pom中指定即可

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

上班摸魚寫博客, 晚上只好加班~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM