java異常體系及1.7中的try-with-resources

1.java異常體系架構(gòu)

異常指java運(yùn)行過程出現(xiàn)的錯(cuò)誤,在java中,將異常當(dāng)作對(duì)象來處理,java.lang.Throwable是所有異常的超類。其架構(gòu)如下圖:


image.png

1.1 Throwable

Throwable是 Java 語言中所有錯(cuò)誤或異常的超類。
 Throwable包含兩個(gè)子類: Error 和 Exception。用于標(biāo)識(shí)具體的異常情況。

1.2 Error

Error指程序無法處理的錯(cuò)誤,當(dāng)出現(xiàn)這些錯(cuò)誤時(shí),jvm通常會(huì)終止程序的運(yùn)行。Error常見的子類有java.lang.StackOverFlowError和Java.lang.OutOfMemoryError等。java編譯器不會(huì)檢查error及其子類。

1.3 Exception

Exception 是Throwable的子類,指程序本身可以處理的錯(cuò)誤。遇到此類異常,應(yīng)該盡可能的處理異常,使程序恢復(fù)運(yùn)行,而不是隨意終止異常。

1.4 RuntimeException

RuntimeException及其子類也叫運(yùn)行時(shí)異常,如NullPointerException、IndexOutOfBoundsException等,這些異常編譯器不會(huì)檢查,此類異常通常由邏輯錯(cuò)誤引起,從程序和邏輯角度應(yīng)當(dāng)避免這類異常的發(fā)生。

1.5受檢異常和非受檢異常

受檢異常:指Exception中除RuntimeException之外的所有異常,此類問題通常不是很嚴(yán)重,經(jīng)過合適的處理,程序還可以正常執(zhí)行流程,因此java編譯器會(huì)要求對(duì)此類異常進(jìn)行處理,否則不能編譯。
非受檢異常:包括RuntimeException 和Error,通常情況下,RuntimeException是由于邏輯造成,java編譯器不會(huì)對(duì)此類異常強(qiáng)制要求處理,應(yīng)由程序員選擇是否處理。Error則是由于jvm內(nèi)部出現(xiàn)嚴(yán)重問題,無法進(jìn)行恢復(fù),因此java編譯器也不會(huì)要求此類異常強(qiáng)制處理。

2.try、catch、finally處理java異常機(jī)制存在的小問題

在java中通常用 try、catch、finally語句塊對(duì)異常進(jìn)行處理,在這個(gè)處理邏輯中,catch捕獲到異常則可拋出,但是如果catch捕獲異常后,finally語句塊中也有新的異常同時(shí)throw,則在調(diào)用該方法時(shí),之前catch語句塊中throw的異常會(huì)丟失。

public class ExceptionTest {

    public static void main(String[] args) {
        try {
            testException();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void testException() throws Exception{
        try {
            int a = 1/0;
        } catch (Exception e) {
            Exception exception = new Exception("catch exception ");
            exception.addSuppressed(e);
            throw exception;
        }finally {
            try {
                int b = 1/0;
            } catch (Exception e) {
                Exception exception = new Exception("finally exception ");
                exception.addSuppressed(e);
                throw exception;
            }
        }
    }
}

執(zhí)行上述類,發(fā)現(xiàn)最終在main函數(shù)中只捕獲到了finally語句塊中的exception。

java.lang.Exception: finally exception 
    at com.dhb.exception.ExceptionTest.testException(ExceptionTest.java:24)
    at com.dhb.exception.ExceptionTest.main(ExceptionTest.java:7)
    Suppressed: java.lang.ArithmeticException: / by zero
        at com.dhb.exception.ExceptionTest.testException(ExceptionTest.java:22)
        ... 1 more

對(duì)于此類問題,在jdk1.7中,加入了兩個(gè)方法幫助我們能夠很好的去解決這個(gè)問題了,那就是addSuppressed(Throwable exception)和getSuppressed()。
如下通過addSuppressed進(jìn)行處理:

public class ExceptionTest {

    public static void main(String[] args) {
        try {
            testSuppressed();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void testSuppressed() throws Exception{
        Exception suppressed = null;
        try {
            int a = 1/0;
        } catch (Exception e) {
            Exception exception = new Exception("catch exception ");
            exception.addSuppressed(e);
            suppressed = exception;
            throw exception;
        }finally {
            try {
                int b = 1/0;
            } catch (Exception e) {
                Exception exception = new Exception("finally exception ");
                exception.addSuppressed(e);
                if(null != suppressed) {
                    exception.addSuppressed(suppressed);
                }
                throw exception;
            }
        }
    }
}

執(zhí)行結(jié)果:

java.lang.Exception: finally exception 
    at com.dhb.exception.ExceptionTest.testSuppressed(ExceptionTest.java:44)
    at com.dhb.exception.ExceptionTest.main(ExceptionTest.java:7)
    Suppressed: java.lang.ArithmeticException: / by zero
        at com.dhb.exception.ExceptionTest.testSuppressed(ExceptionTest.java:42)
        ... 1 more
    Suppressed: java.lang.Exception: catch exception 
        at com.dhb.exception.ExceptionTest.testSuppressed(ExceptionTest.java:36)
        ... 1 more
        Suppressed: java.lang.ArithmeticException: / by zero
            at com.dhb.exception.ExceptionTest.testSuppressed(ExceptionTest.java:34)
            ... 1 more

這樣catch中的exception就被添加到了StackTrace中。

3.try-with-resources

在jdk1.7中,對(duì)于異常處理,尤其是對(duì)于資源釋放等場(chǎng)景的try、catch、finally執(zhí)行時(shí),可以通過try-with-resources進(jìn)行處理。
用法如下:

static String readFirstLineFromFile(String path) throws IOException {  
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {  
        return br.readLine();  
    }  
}  

其實(shí)這是一個(gè)語法糖,編譯器自動(dòng)在代碼最后面增加了判斷對(duì)象是否為null, 如果不為null,則調(diào)用close。
只有實(shí)現(xiàn)了java.lang.AutoCloseable接口,或者java.io.Closable(實(shí)際上繼隨自java.lang.AutoCloseable)接口的對(duì)象,才會(huì)自動(dòng)調(diào)用其close()函數(shù)。
此外還會(huì)將catch語句塊中的exception通過addSuppressed對(duì)異常進(jìn)行保存。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容