天天看點

JDK9新特性實戰:簡化流關閉新姿勢。

image

做Java開發的都知道,每個資源的打開都需要對應的關閉操作,不然就會使資源一直占用而造成資源浪費,進而降低系統性能。

關于資源的關閉操作,從JDK7-JDK9有了不少的提升及簡化。

JDK6

在JDK6及之前,每個資源都需要我們手動寫代碼關閉,如:

FileInputStream fis = null;
byte[] buffer = new byte[1024];
try {
    fis = new FileInputStream(new File("E:\\Java技術棧.txt"));
    while (fis.read(buffer) > 0) {
        System.out.println(new String(buffer));
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    if (fis != null) {
        try {
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
           

資源打開使用完後,必須在finally塊中進行手動關閉!我們有的同僚,做一個查詢功能點,打開了連接配接查詢完後沒有手動關閉,最後造成連接配接池超出最大連接配接數而使系統功能堵塞。

JDK7

JDK7釋出後,添加了新特性:try-with-resources語句。所有需要關閉的資源隻要實作了

java.lang.AutoCloseable

(java.io.Closeable就實作了這個接口)接口就在會程式結束後自動關閉。

如上面的讀取檔案的流程式用JDK7來寫:

byte[] buffer = new byte[1024];
try (FileInputStream fis = new FileInputStream(new File("E:\\Java技術棧.txt"))) {
    while (fis.read(buffer) > 0) {
        System.out.println(new String(buffer));
    }
} catch (Exception e) {
    e.printStackTrace();
}
           

所有的資源在

try()

裡面定義,并去掉了finally子產品。

下面我們來寫一個自定義的流來看看是否自動關閉了。

定義一個自定義輸入輸出流

class MyInputStream implements AutoCloseable {

    void read(String content) {
        System.out.println("read content " + content);
    }

    @Override
    public void close() throws Exception {
        System.out.println("input stream is closed.");
    }

}

class MyOutputStream implements AutoCloseable {

    void write(String content) {
        System.out.println("write content " + content);
    }

    @Override
    public void close() throws Exception {
        System.out.println("out stream is closed.");
    }

}
           

單個資源自動關閉

try (MyInputStream mis = new MyInputStream()) {
    mis.read("7_2");
} catch (Exception e) {
    e.printStackTrace();
}
           

輸出:

read content 7_2

input stream is closed.

多個資源自動關閉

try()

裡面可以定義多個資源,它們的關閉順序是最後在

try()

定義的資源先關閉。

try (MyInputStream mis = new MyInputStream(); MyOutputStream mos = new MyOutputStream()) {
    mis.read("7_3");
    mos.write("7_3");
} catch (Exception e) {
    e.printStackTrace();
}
           

read content 7_3

write content 7_3

out stream is closed.

JDK9

JDK9釋出後,又簡化了try-with-resources語句的用法。

try()

裡面可以是一個變量,但必須是final的或者等同final才行。如下面的mis,mos定義成局部變量可以不用final,局部變量可以等同于final,但定義成成員變量就必須是用final修飾的,不然會編譯錯誤。

MyInputStream mis = new MyInputStream();
MyOutputStream mos = new MyOutputStream();
try (mis; mos) {
    mis.read("1.9");
    mos.write("1.9");
} catch (Exception e) {
    e.printStackTrace();
}
           

read content 1.9

write content 1.9

再來看個例子:

Connection dbCon = DriverManager.getConnection("url", "user", "password");
try (dbCon; ResultSet rs = dbCon.createStatement().executeQuery("select * from emp")) {
    while (rs.next()) {
        System.out.println("In loadDataFromDB() =====>>>>>>>>>>>> " + rs.getString(1));
    }
} catch (SQLException e) {
    System.out.println("Exception occurs while reading the data from DB ->" + e.getMessage());
}
           

dbCon和rs都能被自動關閉。

JKD9雖然簡化了,但感覺還是沒有什麼質的變化,實際用途我們可能不希望關心資源的關閉,或者在方法結束之後如果是局部變量它就能自動關閉。或許是我站的高度不夠,官方有其他的考量,但JDK9的這一點變化還是非常有用的。

更多JDK9的新功能實戰陸續更新,如果覺得有用,分享到朋友圈給更多的人吧!

推薦:

成為架構師的十階段學習資料 Spring Boot & Cloud 最強技術教程 分享一套進階Java筆試題(實拍高清圖)

如果對你有用,歡迎分享到朋友圈