Java try()語句實(shí)現(xiàn)try-with-resources異常管理機(jī)制操作
Java try()語句實(shí)現(xiàn)try-with-resources異常管理機(jī)制
java7 新增特性,對(duì)于try語句塊中使用到的資源,不再需要手動(dòng)關(guān)閉,在語句塊結(jié)束后,會(huì)自動(dòng)關(guān)閉,類似于python的with..as的用法。
利用這個(gè)特性,需要實(shí)現(xiàn)AutoCloseable接口,只有一個(gè)close方法,實(shí)現(xiàn)關(guān)閉資源的操作。
public interface AutoCloseable{
public void close() throws Exception;
}
所有的流,都實(shí)現(xiàn)了這個(gè)接口,可以在try()中進(jìn)行實(shí)例化。自定義的類只要實(shí)現(xiàn)了這個(gè)接口,也可以使用這個(gè)特性。
不使用try-with-resources時(shí),使用的資源要在finally中進(jìn)行釋放
package stream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class TestStream {
public static void main(String[] args) {
File f = new File("d:/test.txt");
FileInputStream fis = null;
try {
fis = new FileInputStream(f);
} catch (IOException e) {
e.printStackTrace();
} finally {
// 在finally 里關(guān)閉流
if (null != fis)
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
使用try-with-resources時(shí)
形式為try(),括號(hào)內(nèi)可以包含多個(gè)語句。
package stream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class TestStream {
public static void main(String[] args) {
File f = new File("d:/lol.txt");
//把流定義在try()里,try,catch或者finally結(jié)束的時(shí)候,會(huì)自動(dòng)關(guān)閉
try (FileInputStream fis = new FileInputStream(f)) {
byte[] all = new byte[(int) f.length()];
fis.read(all);
for (byte b : all) {
System.out.println(b);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
自定義AutoCloseable實(shí)現(xiàn)
在TestAutoCloseable的close方法中打印信息
package test;
public class TestAutoCloseable implements AutoCloseable{
public TestAutoCloseable() {
System.out.println("class TestAutoCloceable");
}
public void close() {
System.out.println("function close() executed");
}
}
測(cè)試代碼
package test;
public class TestFeature {
public static void main(String[] args) {
// TODO Auto-generated method stub
try(TestAutoCloseable testAutoCloseable = new TestAutoCloseable()){
}
}
}
結(jié)果close方法被調(diào)用

try-with-resources語句優(yōu)雅的關(guān)閉資源
在Java編程過程中,如果打開了外部資源(文件、數(shù)據(jù)庫連接、網(wǎng)絡(luò)連接等),我們必須在這些外部資源使用完畢后,手動(dòng)關(guān)閉它們。
因?yàn)橥獠抠Y源不由JVM管理,無法享用JVM的垃圾回收機(jī)制,如果我們不在編程時(shí)確保在正確的時(shí)機(jī)關(guān)閉外部資源,就會(huì)導(dǎo)致外部資源泄露,緊接著就會(huì)出現(xiàn)文件被異常占用,數(shù)據(jù)庫連接過多導(dǎo)致連接池溢出等諸多很嚴(yán)重的問題。
在java1.7以前,我們關(guān)閉資源的方式如下
public class CloseTest {
public static void main(String[] args){
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream("file.txt");
fileInputStream.read();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fileInputStream != null){
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
為了確保外部資源一定要被關(guān)閉,通常關(guān)閉代碼被寫入finally代碼塊中,關(guān)閉資源時(shí)可能拋出的異常,于是經(jīng)典代碼就誕生了。
但是,在java1.7版本之后,新增加了一個(gè)語法糖,就是try-with-resources語句,
我們先直接上一個(gè)demo,方便理解
public class CloseTest {
public static void main(String[] args) {
try (FileInputStream fileInputStream1 = new FileInputStream("file1.txt");
FileInputStream fileInputStream2 = new FileInputStream("file2.txt")) {
fileInputStream1.read();
fileInputStream2.read();
} catch (IOException e) {
e.printStackTrace();
}
}
}
將外部資源的句柄對(duì)象的創(chuàng)建放在try關(guān)鍵字后面的括號(hào)中,當(dāng)這個(gè)try-catch代碼塊執(zhí)行完畢后,Java會(huì)確保外部資源的close方法被調(diào)用。多個(gè)語句使用分號(hào)斷開。
反編譯之后我們可以看見
public static void main(String[] args) {
try {
FileInputStream inputStream = new FileInputStream(new File("test"));
Throwable var2 = null;
try {
System.out.println(inputStream.read());
} 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);
}
}
通過反編譯的代碼,大家可能注意到代碼中有一處對(duì)異常的特殊處理:
var2.addSuppressed(var11);
這是try-with-resource語法涉及的另外一個(gè)知識(shí)點(diǎn),叫做異常抑制。當(dāng)對(duì)外部資源進(jìn)行處理(例如讀或?qū)懀r(shí),如果遭遇了異常,且在隨后的關(guān)閉外部資源過程中,又遭遇了異常,那么你catch到的將會(huì)是對(duì)外部資源進(jìn)行處理時(shí)遭遇的異常,關(guān)閉資源時(shí)遭遇的異常將被“抑制”但不是丟棄,通過異常的getSuppressed方法,可以提取出被抑制的異常。
源碼里面有解釋
/**
* Returns an array containing all of the exceptions that were
* suppressed, typically by the {@code try}-with-resources
* statement, in order to deliver this exception.
*
* If no exceptions were suppressed or {@linkplain
* #Throwable(String, Throwable, boolean, boolean) suppression is
* disabled}, an empty array is returned. This method is
* thread-safe. Writes to the returned array do not affect future
* calls to this method.
*
* @return an array containing all of the exceptions that were
* suppressed to deliver this exception.
* @since 1.7
*/
public final synchronized Throwable[] getSuppressed() {
if (suppressedExceptions == SUPPRESSED_SENTINEL ||
suppressedExceptions == null)
return EMPTY_THROWABLE_ARRAY;
else
return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
}
總結(jié)一下吧
因?yàn)椴还苁裁辞闆r下(異常或者非異常)資源都必須關(guān)閉,在jdk1.6之前,應(yīng)該把close()放在finally塊中,以確保資源的正確釋放。如果使用jdk1.7以上的版本,推薦使用try-with-resources語句。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java調(diào)用mysql存儲(chǔ)過程實(shí)例分析
這篇文章主要介紹了java調(diào)用mysql存儲(chǔ)過程的方法,以實(shí)例形式較為詳細(xì)的分析了mysql數(shù)據(jù)庫的建立和存儲(chǔ)過程的實(shí)現(xiàn)方法,需要的朋友可以參考下2015-06-06
SpringBoot整合Mybatis實(shí)現(xiàn)CRUD
這篇文章主要介紹了SpringBoot整合Mybatis實(shí)現(xiàn)CRUD的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09
java使用計(jì)算md5校驗(yàn)碼方式比較兩個(gè)文件是否相同
MD5文件效驗(yàn)碼是一個(gè)判斷文件是否是相同文件的途徑,通過比較兩個(gè)文件的Md5效驗(yàn)碼是否相同來精確判斷兩個(gè)文件是否相同2014-04-04
如何將默認(rèn)的maven倉庫改為阿里的maven倉庫
這篇文章主要介紹了如何將默認(rèn)的maven倉庫改為阿里的maven倉庫,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12

