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

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)行保存。