Java 7 新特性之try-with-resources實踐理解

 

想像這麼一個情景,我們需要使用一個資源,在使用完之後需要關閉該資源,並且使用該資源的過程中有可能有異常拋出。此時我們都會想到用try-catch語句,在finally中關閉該資源。此時會有一個問題,如果關閉該資源的時候也拋出了異常呢?見如下例子:

package com.rundong;

import java.io.IOException;

public class ResourceTest implements AutoCloseable{
    @Override
    public void close() throws IOException {
        throw new IOException("close Exception");
    }
}
package com.rundong;

import java.io.IOException;
import java.sql.SQLException;

public class Main {
    public static void main(String[] args) {
        try {
            throwTest();
        } catch (SQLException e) {
            System.out.println("catch SQLException");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("catch IOException");
            e.printStackTrace();
        }
    }

    static void throwTest() throws SQLException, IOException {
        ResourceTest resource = null;
        try {
            resource = new ResourceTest();
            throw new SQLException("the first Exception");
        } catch (SQLException e) {
            System.out.println("catch the first Exception");
            // do something
            throw e;
        } finally {
            if (resource != null) resource.close();
        }
    }
}

輸出結果:

 發現什麼問題了嗎?

finally中拋出的異常將try中拋出的異常覆蓋了!我們無法捕獲到第一個異常!

 

Java 7 的解決方式:

package com.rundong;

import java.io.IOException;
import java.sql.SQLException;

public class Main {
    public static void main(String[] args) {
        try {
            throwTest();
        } catch (SQLException e) {
            System.out.println("catch SQLException");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("catch IOException");
            e.printStackTrace();
        }
    }

    static void throwTest() throws SQLException, IOException {
        try (ResourceTest resource = new ResourceTest()) {
            throw new SQLException("the first Exception");
        } catch (SQLException e) {
            System.out.println("catch the first Exception");
            // do something
            throw e;
        }
    }
}

 

輸出結果:

 try-with-resources的寫法就能很好的處理這樣的情景,它會自動關閉資源,並且如果關閉資源時也拋出了異常,不會覆蓋原有異常的拋出。

使用條件:實現了AutoCloseable介面的類。

 

同時,這也提示著我們,永遠不要嘗試在finally中拋出異常!

Tags: