一解幼、異常的概念
異常是在程序中導(dǎo)致程序中斷運行的一種指令流,一旦產(chǎn)生異常之后润绎,異常之后的語句將不再執(zhí)行了撬碟,程序序并沒有正確的執(zhí)行完畢之后就退出了。
二莉撇、處理異常
1呢蛤、try catch塊
try{
// 有可能發(fā)生異常的代碼段
}catch(異常類型1 對象名1){
// 異常的處理操作
}catch(異常類型2 對象名2){
// 異常的處理操作
} ...
finally{
// 異常的統(tǒng)一出口
}
2、處理流程:
- 一旦產(chǎn)生異常棍郎,則系統(tǒng)會自動產(chǎn)生一個異常類的實例化對象其障。
- 那么,此時如果異常發(fā)生在try語句涂佃,則會自動找到匹配的catch語句執(zhí)行励翼,如果沒有在try語句中,則會將異常拋出.
- 所有的catch根據(jù)方法的參數(shù)匹配異常類的實例化對象辜荠,如果匹配成功汽抚,則表示由此catch進行處理。
異常調(diào)用的順序:
3伯病、finally塊
必然執(zhí)行造烁,除非關(guān)機、斷電等程序從內(nèi)存中釋放的行為午笛,以及try-catch塊中的System.exit()的程序退出行為惭蟋。
三、異常的體系結(jié)構(gòu)
異常指的是Exception 药磺, Exception類敞葛, 在Java中存在一個父類Throwable(可能的拋出)。Exception位于java.lang包下与涡,它是一種頂級接口,繼承于Throwable類持偏,Exception類及其子類都是Throwable 的組成條件驼卖,是程序出現(xiàn)的合理情況。Throwable類是Java語言中所有錯誤(errors)和異常(exceptions)的父類鸿秆。只有繼承于Throwable的類或者其子類才能夠被拋出酌畜,還有一種方式是帶有Java中的@throw注解的類也可以拋出。
Throwable存在兩個子類:
- Error:表示的是錯誤卿叽,是JVM發(fā)出的錯誤操作,只能盡量避免桥胞,無法用代碼處理恳守。
- Exception:一般表示所有程序中的錯誤,所以一般在程序中將進行try…catch的處理贩虾。
Throwable的常用方法:
//返回拋出異常的詳細信息
public string getMessage();
public string getLocalizedMessage();
//返回異常發(fā)生時的簡要描述
public public String toString();
//打印異常信息到標準輸出流上
public void printStackTrace();
public void printStackTrace(PrintStream s);
public void printStackTrace(PrintWriter s);
//記錄棧幀的當前狀態(tài)
public synchronized Throwable fillInStackTrace();
此外催烘,因為Throwable 的父類也是0bject ,所以常用的方法還有繼承其父類的 getClass()和getName(方法缎罢。
繼承圖:
受檢查的異常在編寫代碼時必然會有錯誤提示伊群,必須將其拋出,運行時的非受檢異常編譯時不會報錯策精,運行時才會發(fā)現(xiàn)舰始,可以選擇拋出和處理。拋出的原則是咽袜,如果是由于傳入方法的參數(shù)所導(dǎo)致的錯誤丸卷,則選擇拋出異常,誰調(diào)用誰處理询刹。
RuntimeException:
UncheckedException:
多異常捕獲:
- 捕獲更粗的異常不能放在捕獲更細的異常之前谜嫉。
- 如果為了方便,則可以將所有的異常都使用Exception進行捕獲范抓。
// 另一種寫法
catch(異常類型1 |異常類型2 對象名){
//表示此塊用于處理異常類型1 和 異常類型2 的異常信息
}
四骄恶、throws與throw
聲明方法時使用throws表示方法不處理,調(diào)用者處理匕垫。
返回值 方法名稱()throws Exception{
}
throw字表示在程序中人為的拋出一個異常僧鲁,因為從異常處理機制來看,所有的異常一旦產(chǎn)生之后象泵,實際上拋出的就是一個異常類的實例化對象寞秃,那么此對象也可以由throw直接拋出。(不太友好的方式偶惠,通過程序的中斷來進行錯誤提示)春寿。
throw new Exception("拋著玩的。") ;
五忽孽、RuntimeExcepion與Exception的區(qū)別
Integer類: public static int parseInt(String text)throws NumberFormatException
此方法拋出了異常绑改, 但是使用時卻不需要進行try...catch捕獲處理,原因: 因為NumberFormatException并不是Exception的直接子類兄一,
而是RuntimeException的子類厘线,只要是 RuntimeException的子類,則表示程序在操作的時候可以不必使用try...catch進行處理出革,如果有異常發(fā)生造壮,
則由JVM進 行處理。當然骂束,也可以通過try catch處理耳璧。
六成箫、自定義異常
自定義異常可以做很多事情旨枯, 例如:
class MyException extends Exception{
public MyException(String msg){
super(msg) ;
//在這里給維護人員發(fā)短信或郵件蹬昌, 告知程序出現(xiàn)了BUG。
}
};
七召廷、面試題
1. try-catch-finally 中哪個部分可以省略凳厢?
答: catch和finally可以省略其中一個 , catch和finally不能同時省略
注意:格式上允許省略catch塊, 但是發(fā)生異常時就不會捕獲異常了,我們在開發(fā)中也不會這樣去寫代碼.
2. try-catch-finally 中竞慢,如果 catch 中 return 了先紫,finally 還會執(zhí)行嗎?
答:finally中的代碼會執(zhí)行
詳解:
執(zhí)行流程:
1. 先計算返回值筹煮, 并將返回值存儲起來遮精, 等待返回
2. 執(zhí)行finally代碼塊
3. 將之前存儲的返回值, 返回出去败潦;
需注意:
1. 返回值是在finally運算之前就確定了本冲,并且緩存了,不管finally對該值做任何的改變劫扒,返回的值都不
會改變(區(qū)分基本數(shù)據(jù)類型與引用數(shù)據(jù)類型)
2. finally代碼中不建議包含return檬洞,因為程序會在上述的流程中提前退出,也就是說返回的值不是try或
catch中的值
3. 如果在try或catch中停止了JVM,則finally不會執(zhí)行.例如停電- -, 或通過如下代碼退出
JVM:System.exit(0);
八沟饥、什么是Error
Error是程序無法處理的錯誤添怔,表示運行應(yīng)用程序中較嚴重問題。大多數(shù)錯誤與代碼編寫者執(zhí)行的操作無關(guān)贤旷,而表示代碼運行時JVM(Java 虛擬機)出現(xiàn)的問題广料。這些錯誤是不可檢查的,因為它們在應(yīng)用程序的控制和處理能力之外幼驶,而且絕大多數(shù)是程序運行時不允許出現(xiàn)的狀況艾杏,比如OutOfMemoryError和StackOverflowError異常的出現(xiàn)會有幾種情況,這里需要先介紹一下Java內(nèi)存模型JDK1.7盅藻。
其中包括兩部分购桑,由所有線程共享的數(shù)據(jù)區(qū)和線程隔離的數(shù)據(jù)區(qū)組成,在上面的Java內(nèi)存模型中氏淑,只有程序計數(shù)器是不會發(fā)生OutOfMemoryError情況的區(qū)域勃蜘,程序計數(shù)器控制著計算機指令的分支、循環(huán)夸政、跳轉(zhuǎn)、異常處理和線程恢復(fù)榴徐,并且程序計數(shù)器是每個線程私有的守问。
什么是線程私有:表示的就是各條線程之間互不影響匀归,獨立存儲的內(nèi)存區(qū)域。
如果應(yīng)用程序執(zhí)行的是Java方法耗帕,那么這個計數(shù)器記錄的就是虛擬機字節(jié)碼指令的地址;如果正在執(zhí)行的是 Native方法穆端,這個計數(shù)器值則為空(Undefined)。
除了程序計數(shù)器外仿便,其他區(qū)域:方法區(qū)(Method Area)体啰、虛擬機棧(VM Stack)、本地方法棧(Native Method Stack)和堆(Heap)都是可能發(fā)生OutOfMemoryError的區(qū)域嗽仪。
- 虛擬機棧︰如果線程請求的棧深度大于虛擬機棧所允許的深度荒勇,將會出現(xiàn)StackOverflowError異常;如果虛擬機動態(tài)擴展無法申請到足夠的內(nèi)存,將出現(xiàn)OutOfMemoryError 闻坚。
- 本地方法棧和虛擬機椆料瑁—樣
- 堆: Java堆可以處于物理上不連續(xù),邏輯上連續(xù)窿凤,就像我們的磁盤空間一樣仅偎,如果堆中沒有內(nèi)存完成實例分配,并且堆無法擴展時雳殊,將會拋出OutOfMemoryError橘沥。
- 方法區(qū)︰方法區(qū)無法滿足內(nèi)存分配需求時,將拋出OutOfMemoryError異常夯秃。
在Java中座咆,你可以把異常理解為是一種能夠提高你程序健壯性的機制,它能夠讓你在編寫代碼中注意這些問題寝并。