一堕担、概述
Java中, 所以的異常都繼承自java.lang.Throwable
。
Throwable
: Throwable是Java中所有錯誤(error)和異常(Exception)的父類讽营。 錯誤和異常的區(qū)別是異常可以被應(yīng)用程序處理叁巨, 而錯誤無法被處理斑匪。Error
: Error是無法處理的錯誤, 表示程序運行中出現(xiàn)比較嚴(yán)重的問題锋勺。大多數(shù)Error和代碼編寫者無關(guān)蚀瘸, 表示代碼運行時JVM(Java虛擬機)出現(xiàn)的問題。Exception
: Exception是程序自身可以處理的異常庶橱,Exception有一個重要的子類RuntimeException
, 代表運行時異常贮勃。這些異常時非檢查異常, 應(yīng)用程序中可以處理苏章,也可以不處理寂嘉,一般是由程序錯誤邏輯引起的奏瞬。除過非檢出異常, 其他的異常都是檢查異常泉孩, 檢查異常如果不處理硼端, 程序就無法編譯通過。
二寓搬、異常(Exception)
1珍昨、檢查異常(CheckedException)
程序運行中,很容易出現(xiàn)的句喷、情理可容的異常镣典。除了RuntimeException
及其子類外, 其他的都是檢出異常唾琼。檢出異常必須被處理兄春, Java編譯器會檢查這種異常, 當(dāng)遇到這種異常時锡溯,要么使用try/catch
捕獲它赶舆, 要么使用throw
拋出它。
常見的檢查異常:
序號 | 異常名稱 | 異常描述 |
---|---|---|
1 | NoSuchFieldException | 表示該類沒有指定名稱拋出來的異常 |
2 | NoSuchMethodException | 表示該類沒有指定方法拋出來的異常 |
3 | IllegalAccessException | 不允許訪問某個類的異常 |
4 | ClassNotFoundException | 類沒有找到拋出異常 |
5 | IOException | IO錯誤 |
2趾唱、非檢查異常 (UnCheckedException)
包括運行時異常RuntimeExcption
和Error
以及其子類涌乳,表示編譯器不會檢查程序是否對其做了處理, 出現(xiàn)運行時異常時甜癞,表示程序出現(xiàn)了錯誤夕晓, 需要找出異常并修正它。
序號 | 異常名稱 | 異常描述 |
---|---|---|
1 | ArrayIndexOutOfBoundsException | 數(shù)組越界異常 |
2 | NullPointerException | 空指針異常 |
3 | IllegalArgumentException | 非法參數(shù)異常 |
4 | NegativeArraySizeException | 數(shù)組長度為負(fù)異常 |
5 | IllegalStateException | 非法狀態(tài)異常 |
6 | ClassCastException | 類型轉(zhuǎn)換異常 |
三悠咱、異常處理
1蒸辆、異常處理的關(guān)鍵字
-
throw
: 在方法內(nèi)部, 代表拋出這個異常析既。 -
thorws
: 在方法的聲明中躬贡, 聲明程序可能會拋出異常, 由方法的調(diào)用者處理眼坏。 -
try/catch
: 代表捕獲異常拂玻。 -
finally
: 無論是否發(fā)生異常, 都會經(jīng)過finally包含的語句在返回宰译。
2檐蚜、try-with-resources
Java中很多類庫都需要在使用完成或異常發(fā)生時關(guān)閉資源, 比如Stream
沿侈、Connection
等等闯第, 傳統(tǒng)的處理方式:
// 打開資源
Connection conn = //
try{
// 使用資源
}catch(Exception e){
// 處理異常
}finally{
// 判斷資源是否被關(guān)閉, 如果沒有被關(guān)閉缀拭,則主動關(guān)閉資源
if(conn != null){
// 關(guān)閉資源也可能拋出異常咳短, 需要注意
conn.close();
}
}
凡是繼承自java.io.Closeable
和 java.io.AutoCloseable
的子類都可以使用try-with-resources
方式進(jìn)行關(guān)閉資源:
try(Connection conn = //){ // 打開資源并且在代碼執(zhí)行結(jié)束的時候填帽,無論是否發(fā)生異常, 主動關(guān)閉資源
// 使用資源
}catch{
// 處理異常
}
3咙好、異常處理流程
Q:如果在try/catch
中包含中包含return
語句篡腌, finally
中的代碼是否會執(zhí)行?
W: 一定會執(zhí)行敷扫,finally
語句中的代碼在return
前先執(zhí)行然后再return
哀蘑。
Q: 如果try/catch
和finally
中同時包含return
語句會返回那一個诚卸?
W: 返回finally
語句中返回的內(nèi)容葵第。finally
中包含return
語句時, 會使try/catch
中的return
失效, 最終返回finally
中返回的內(nèi)容.
public class UserClient2 {
public static void main(String[] args) {
System.out.println(test());
}
public static String test(){
try{
throw new Exception("-1");
// return "1";
}catch (Exception e){
return "2";
}finally {
return "3";
}
}
}
// Output
// 無論是否拋出異常合溺, 返回的都是3卒密。
Q: finally
中包含對try/catch
返回內(nèi)容的更新操作, 返回值時try/catch
返回內(nèi)容棠赛, 還是finally
更新后的內(nèi)容哮奇。
W: 如果返回的內(nèi)容時基本類型,則返回的是try/catch
返回的值睛约,如果返回的是引用類型鼎俘, 則返回的是finally
語句更新后的值。
int i = 0;
try{
i ++ ;
System.out.println(i);
return i; // 1
}catch(Exception e){
i ++; // 1
System.out.println(i);
}finally{
i++; // 2
System.out.println(i);
}
// Output
// 1
// 2
// 最終返回的是1
可以看到辩涝,最終返回的是1贸伐, 是因為return
時,會先執(zhí)行return
前的代碼怔揩,然后暫存return
的返回值捉邢, 再執(zhí)行finally
的代碼,最后通過return
返回之前保存的內(nèi)容商膊。所以這里返回的是1伏伐,而不是2, 但是對于下面這個例子晕拆,則不一樣:
List<Integer> valueList = new ArrayList();
try{
valueList.add(1);
System.out.println(valueList);
return valueList;
}catch(Exception e){
valueList.add(2);
System.out.println(valueList);
}finally{
valueList.add(3);
System.out.println(valueList);
}
// Output
// {1,}
// {1,3}
// 最終輸出是{1,3}
最終的輸出是{1,3}, 主要是因為返回的數(shù)據(jù)類型藐翎, 當(dāng)返回的是基本類型時,暫存的內(nèi)容不會改變实幕, 但是返回的是引用類型時吝镣,引用類型存的不是變量本身, 而是對變量的引用茬缩, 所以當(dāng)finllay
改變了變量的內(nèi)容時赤惊,最終返回結(jié)果也會被改變。
總結(jié):
1凰锡、 finally
的內(nèi)容一定會被執(zhí)行未舟。
2圈暗、 當(dāng)try/catch
中包含return
時, finally
的代碼也會被執(zhí)行裕膀。return
的時候需要注意返回的值類型员串, 否則返回值會受到影響。
3昼扛、 finally
中包含return
時寸齐, 會直接返回finaly
中的值, 導(dǎo)致try/catch
中的return
失效抄谐。