什么是異常
異常通常指肉拓,你在編寫代碼時(shí)沒有錯(cuò)誤,在運(yùn)行時(shí)在log控制臺(tái)出現(xiàn)的異常,比如常見的空指針異常。也可能是程序可能出現(xiàn)無法預(yù)料的異常呻拌,比如你要從一個(gè)文件讀信息磷蜀,可這個(gè)文件不存在包雀,程序無法運(yùn)行下去了谢谦,故程序要抓這些異常,通過異常處理機(jī)制來拋出這些異常愿阐,程序員就可以通過拋出的異常來修改代碼微服。try{}catch{}finally{}try塊中放入可能會(huì)出現(xiàn)異常的代碼,catch塊負(fù)責(zé)捕獲異常缨历,finally塊負(fù)責(zé)處理一些必須執(zhí)行的代碼以蕴,比較關(guān)閉流等。
或者使用throws加異常類型拋出異常例如下邊的代碼:
//throws是聲明這個(gè)方法的調(diào)用存在異常情況辛孵,調(diào)用者需要采取捕獲處理活繼續(xù)向外拋的操作才能通過編譯
public static int div(int a, int b) throws ArithmeticException {
//1.當(dāng)這段代碼出現(xiàn)問題時(shí)丛肮,jvm會(huì)創(chuàng)建一個(gè)異常對(duì)象并拋個(gè)調(diào)用者
//2.調(diào)用者接收到異常之后不能處理的話,繼續(xù)往上拋魄缚,再到拋給jvm宝与,最終將異常信息輸出到控制臺(tái)
if (b == 0) {
throw new ArithmeticException("除以0了");
}
return a / b; // 當(dāng)代碼運(yùn)行到這行時(shí)發(fā)現(xiàn)有錯(cuò)誤就會(huì) throw(拋出) new ArithmeticException()在拋出
}
異常處理機(jī)制
Java應(yīng)用程序中,異常處理機(jī)制為:拋出異常冶匹,捕捉異常习劫。
拋出異常:當(dāng)一個(gè)方法出現(xiàn)錯(cuò)誤引發(fā)異常時(shí),方法創(chuàng)建異常對(duì)象并交付運(yùn)行時(shí)系統(tǒng)嚼隘,異常對(duì)象中包含了異常類型和異常出現(xiàn)時(shí)的程序狀態(tài)等異常信息诽里。運(yùn)行時(shí)系統(tǒng)負(fù)責(zé)尋找處置異常的代碼并執(zhí)行。
如何拋出異常:
異常的拋出有兩種方式
第一種:直接在函數(shù)頭中throws SomeException飞蛹,
如下代碼:例子中是描述一種異常的拋出
//throws是聲明這個(gè)方法的調(diào)用存在異常情況谤狡,調(diào)用者需要采取捕獲處理活繼續(xù)向外拋的操作才能通過編譯
public static int div(int a, int b) throws ArithmeticException {
return a / b; // 當(dāng)代碼運(yùn)行到這行時(shí)發(fā)現(xiàn)有錯(cuò)誤就會(huì) throw(拋出) new ArithmeticException()在拋出
}
第二種:使用try/catch匿乃,在catch中進(jìn)行一定的處理之后拋出某種異常。
如下代碼:
try {
computer.setStatus("進(jìn)水");
}catch (EnterWaterException e){
e.printStackTrace();
}
捕獲異常:
在方法拋出之后豌汇,運(yùn)行時(shí)系統(tǒng)將轉(zhuǎn)為尋找合適的異常處理器。潛在的異常處理器是異常發(fā)生時(shí)一次存留在調(diào)用棧中的方法的集合泄隔。當(dāng)異常處理器所有能處理的異常類型與方法拋出的異常類型相符時(shí)拒贱,紀(jì)委合適的異常處理器。運(yùn)行時(shí)系統(tǒng)從發(fā)生異常的方法開始佛嬉,一次會(huì)調(diào)用棧中的方法逻澳,直至找到含有合適異常處理器的方法并執(zhí)行。當(dāng)運(yùn)行時(shí)系統(tǒng)遍歷調(diào)用棧而未找到合適的異常處理器暖呕,則運(yùn)行時(shí)系統(tǒng)終止斜做。同時(shí)意味著Java程序的終止。
捕獲異常是通過try/catch finally 來實(shí)現(xiàn)的
1湾揽、try語句
捕獲異常的第一步就是用try {…}語句指定了一段代碼瓤逼,該段代碼就是一次捕獲并處理異常的范圍。在執(zhí)行過程中库物,該段代碼可能會(huì)產(chǎn)生并拋棄一個(gè)或多個(gè)異常霸旗,因此,它后面的catch語句進(jìn)行捕獲時(shí)也要做相應(yīng)的處理戚揭。
2诱告、catch語句
每個(gè)try語句必須伴隨一個(gè)或多個(gè)catch語句,用于捕獲try代碼塊所產(chǎn)生的異常并做相應(yīng)的處理民晒。 catch語句有一個(gè)形式參數(shù)精居,用于指明其所能捕獲得異常類型,運(yùn)行時(shí)系統(tǒng)通過參數(shù)值把被拋棄的異常對(duì)象傳遞給catch語句
3潜必、finally語句
捕獲異常的最后一步是通過finally語句為異常處理提供一個(gè)統(tǒng)一的出口靴姿,使得在控制流程轉(zhuǎn)到程序的其他部分以前,能夠?qū)Τ绦虻臓顟B(tài)作統(tǒng)一的管理, finally所指定的代碼都要被執(zhí)行
異常的體系結(jié)構(gòu)
Throwable類所有異常和錯(cuò)誤的超類磁滚,有兩個(gè)子類
Error和Exception空猜,分別表示錯(cuò)誤和異常。其中異常類型Exception有分為運(yùn)行時(shí)異常(RuntimeException)和非運(yùn)行時(shí)異常(IOException)恨旱。
Error是程序無法處理的錯(cuò)誤辈毯,(是系統(tǒng)拋出的)比如OutOfMemoryError、ThreadDeath等搜贤。這些異常發(fā)生時(shí)谆沃, Java虛擬機(jī)(JVM)一般會(huì)選擇線程終止。
Exception是程序本身可以處理的異常仪芒,這種異常分兩大類運(yùn)行時(shí)異常和非運(yùn)行時(shí)異常唁影。 程序中應(yīng)當(dāng)盡可能去處理這些異常耕陷。
運(yùn)行時(shí)異常和非運(yùn)行時(shí)異常 :
運(yùn)行時(shí)異常:都是RuntimeException類及其子類異常,如NullPointerException据沈,IndexOutOfBoundsException等哟沫,這些異常是不檢查異常,程序中可以選擇捕獲處理锌介,也可以不處理嗜诀。這些異常一般是由程序邏輯錯(cuò)誤引起,程序應(yīng)該從邏輯角度盡可能避免這類異常的發(fā)生孔祸。
非運(yùn)行時(shí)異常:是RuntimeException以外的異常隆敢,類型上都屬于Exception類及其子類。 從程序語法角度講是必須進(jìn)行處理的異常崔慧,如果不處理拂蝎,程序就不能編譯通過。 如IOException惶室、SQLException等以及用戶自定義的Exception異常温自,一般情況下不自定義檢查異常
使用異常需要注意的問題
1.不要忽略checked Exception。
2.不要一次捕獲所有異常皇钞。
3.使用finally塊釋放資源
4.異常不能影響對(duì)象的狀態(tài)
5.丟失異常
6.不要同時(shí)使用異常機(jī)制和返回值捣作,來進(jìn)行異常處理。
7.不要讓try塊過于龐大
常見異常
- java.lang.nullpointerexception(空指針異常)
這個(gè)異常大家肯定都經(jīng)常遇到鹅士,異常的解釋是"程序遇上了空指針"券躁,簡單地說就是調(diào)用了未經(jīng)初始化的對(duì)象或者是不存在的對(duì)象,這個(gè)錯(cuò)誤經(jīng)常出現(xiàn)在創(chuàng)建圖片掉盅,調(diào)用數(shù)組這些操作中也拜,比如圖片未經(jīng)初始化,或者圖片創(chuàng)建時(shí)的路徑錯(cuò)誤等等趾痘。對(duì)數(shù)組操作中出現(xiàn)空指針慢哈,很多情況下是一些剛開始學(xué)習(xí)編程的朋友常犯的錯(cuò)誤,即把數(shù)組的初始化和數(shù)組元素的初始化混淆起來了永票。數(shù)組的初始化是對(duì)數(shù)組分配需要的空間卵贱,而初始化后的數(shù)組,其中的元素并沒有實(shí)例化侣集,依然是空的键俱,所以還需要對(duì)每個(gè)元素都進(jìn)行初始化(如果要調(diào)用的話) - java.lang.classnotfoundexception(類找不到異常)
這個(gè)異常是很多原本在jb等開發(fā)環(huán)境中開發(fā)的程序員,把jb下的程序包放在wtk下編譯經(jīng)常出現(xiàn)的問題世分,異常的解釋是"指定的類不存在"编振,這里主要考慮一下類的名稱和路徑是否正確即可,如果是在jb下做的程序包臭埋,一般都是默認(rèn)加上package的踪央,所以轉(zhuǎn)到wtk下后要注意把package的路徑加上臀玄。 - java.lang.arithmeticexception(算術(shù)異常)
這個(gè)異常的解釋是"數(shù)學(xué)運(yùn)算異常",比如程序中出現(xiàn)了除以零這樣的運(yùn)算就會(huì)出這樣的異常畅蹂,對(duì)這種異常健无,大家就要好好檢查一下自己程序中涉及到數(shù)學(xué)運(yùn)算的地方,公式是不是有不妥了液斜。 - java.lang.arrayindexoutofboundsexception(數(shù)組越界異常)
這個(gè)異常相信很多朋友也經(jīng)常遇到過累贤,異常的解釋是"數(shù)組下標(biāo)越界",現(xiàn)在程序中大多都有對(duì)數(shù)組的操作旗唁,因此在調(diào)用數(shù)組的時(shí)候一定要認(rèn)真檢查,看自己調(diào)用的下標(biāo)是不是超出了數(shù)組的范圍痹束,一般來說检疫,顯示(即直接用常數(shù)當(dāng)下標(biāo))調(diào)用不太容易出這樣的錯(cuò),但隱式(即用變量表示下標(biāo))調(diào)用就經(jīng)常出錯(cuò)了祷嘶,還有一種情況屎媳,是程序中定義的數(shù)組的長度是通過某些特定方法決定的,不是事先聲明的论巍,這個(gè)時(shí)候烛谊,最好先查看一下數(shù)組的length,以免出現(xiàn)這個(gè)異常嘉汰。 - java.lang.illegalaccessexception(安全權(quán)限異常)
這個(gè)異常的解釋是"沒有訪問權(quán)限"丹禀,當(dāng)應(yīng)用程序要調(diào)用一個(gè)類,但當(dāng)前的方法即沒有對(duì)該類的訪問權(quán)限便會(huì)出現(xiàn)這個(gè)異常鞋怀。對(duì)程序中用了package的情況下要注意這個(gè)異常双泪。