帶你了解Java中的異常處理(上)
當(dāng)當(dāng)當(dāng)當(dāng)當(dāng)當(dāng),各位看官,好久不見,甚是想念。
今天我們來聊聊Java里的一個(gè)小妖精,那就是異常。
什么是異常?什么是異常處理?
異常嘛,顧名思義就是不正常,(逃),是Java程序運(yùn)行時(shí),發(fā)生的預(yù)料之外的事情,它阻止了程序按照程序員的預(yù)期正常執(zhí)行。
異常處理,應(yīng)該說異常處理機(jī)制,就是專門用來制服這個(gè)小妖精的法寶。Java中的異常處理機(jī)制能讓程序在異常發(fā)生時(shí),按照代碼的預(yù)先設(shè)定的異常處理邏輯,針對(duì)性地處理異常,讓程序盡最大可能恢復(fù)正常并繼續(xù)執(zhí)行,且保持代碼的清晰。
簡(jiǎn)而言之,Java異常處理就是能讓我們主動(dòng)迎擊可能到來的異常,并將它們以圓潤的方式處理掉。
還是先來看個(gè)小栗子,看看java里的異常長什么樣。
public class Test { public static void main(String args[]){ int i = 0 / 0; System.out.println("i = " + i); } }
別慌別慌,不要看到紅色提示就內(nèi)心崩潰只想關(guān)掉IDE,來,抓緊我的手,帶你看清“異?!边@個(gè)磨人的小妖精的真面目(滑稽)。
代碼里將0作為了分母,因此程序會(huì)發(fā)生算術(shù)異常,拋出一個(gè)異常后,如果沒有任何處理,默認(rèn)會(huì)終止程序,所以后面的打印內(nèi)容并沒有輸出。在異常內(nèi)容里,有說明異常類型為:java.lang.ArithmeticException,也就是算術(shù)異常,后面跟著的是異常原因: / by zero,也就是說異常出現(xiàn)的原因是將0作為了分母,而且后面還有堆棧信息,指出了異常拋出的位置是在com.frank.chapter16.main.Test.main這個(gè)包下,Test類的第11行(這個(gè)行數(shù)如果跟你想的不一樣,不要在意,因?yàn)槲业拇a開始之前還有一些不可描述的說明信息),因?yàn)橹挥幸淮畏椒ㄕ{(diào)用,所以沒有很長的堆棧信息,看起來也很簡(jiǎn)潔明了。
所以你看,其實(shí)異常也沒那么可怕吧,不僅給了異常原因,還告訴了你這個(gè)bug是出在第幾行,所以好好利用它,可以幫助你寫出更難以發(fā)現(xiàn)的bug,呸,說錯(cuò)了,可以幫助你更容易找到bug(手動(dòng)滑稽)。
如果不希望拋出異常后程序就結(jié)束,而是希望它繼續(xù)運(yùn)行呢?那么就捕獲它。
如何使用異常處理
我們來把上面那個(gè)栗子改改:
public class Test { public static void main(String args[]){ try{ int i = 0 / 0; }catch (Exception e){ System.out.println("好像發(fā)生異常了,但是我不管,我還要繼續(xù)運(yùn)行"); } System.out.println("運(yùn)行完畢!"); } }
輸出如下:
好像發(fā)生異常了,但是我不管,我還要繼續(xù)運(yùn)行
運(yùn)行完畢!
好的,很強(qiáng)勢(shì),現(xiàn)在即使拋出了異常,程序也繼續(xù)運(yùn)行了。異常就像是一頭野獸,但你一旦捕獲它,馴服它,就可以為你所用,為所欲為了。
try...catch...是常用的異常處理搭配,如果在try語句塊中發(fā)生了異常,如果剛好這個(gè)異常被捕獲到了,那么會(huì)直接跳到catch語句塊中,執(zhí)行catch語句中的代碼,像上面的栗子里,因?yàn)閷?duì)Exception類進(jìn)行了捕獲處理,所以當(dāng)它的子類異常java.lang.ArithmeticException被拋出來的時(shí)候,也能捕獲它。關(guān)于Exception類的結(jié)構(gòu)層次關(guān)系,后面再做詳細(xì)介紹。
還有另外一種搭配方式,那就是try...catch...finally,finally語句塊比catch要強(qiáng)勢(shì)的多,前面說了catch語句塊必須要捕獲到了特定的Exception才會(huì)執(zhí)行里面的代碼,如果catch的是ArithmeticException但是拋出的卻是空指針異常,那就不會(huì)被捕獲了,異常也就逃之夭夭了。這個(gè)時(shí)候,finally的優(yōu)勢(shì)就展示出來了,不管拋出什么樣的異常,也不管是否拋出了異常,finally中的代碼都會(huì)被執(zhí)行。所以一般的用法是在finally語句塊里釋放掉那些需要被釋放的資源,如socket連接,關(guān)閉io流,關(guān)閉數(shù)據(jù)庫連接等等。也就是說一般在finally中收拾try中拋出的爛攤子,心疼一秒finally,果然能者多勞啊。
當(dāng)然,try...finally這樣的搭配也是ok的,需要注意的是,當(dāng)try語句中發(fā)生了異常之后,在發(fā)生異常處之后的代碼將不會(huì)再執(zhí)行,而是跳到相應(yīng)的catchu或者finally中去。
public class Test { public static void main(String args[]){ try{ int i = 0 / 0; }catch (NullPointerException e) { System.out.println("這里捕獲空指針異常"); }catch (ArithmeticException e){ System.out.println("這里捕獲算術(shù)異常"); }finally { System.out.println("這里是finally"); } System.out.println("運(yùn)行完畢!"); } }
輸出如下:
這里捕獲算術(shù)異常
這里是finally
運(yùn)行完畢!
在上面的代碼中,catch語句塊是可以同時(shí)使用多個(gè)的,第一個(gè)catch語句塊捕獲的是空指針異常,但由于拋出的是算術(shù)異常,所以沒有捕獲住,但被第二個(gè)catch捕獲到了,所以第二個(gè)catch語句塊中的代碼執(zhí)行了。異常匹配是按照從上到下的順序進(jìn)行匹配的,最后才執(zhí)行finally中的代碼塊。關(guān)于try...catch...finally,還有一個(gè)很有趣的return問題,如果三個(gè)語句塊里都有return,最終返回結(jié)果會(huì)是怎樣呢?www.dbjr.com.cn/article/112427.htm這里做了詳細(xì)的說明,有興趣的話可以看一看
絕大多數(shù)情況下,finally中的代碼都是會(huì)被執(zhí)行的,只有一種情況下,finally中的代碼不會(huì)被執(zhí)行,那就是在try語句塊中結(jié)束掉了虛擬機(jī)(如:使用 System.exit(0); )。
關(guān)于異常,還有一個(gè)關(guān)鍵字需要介紹,那就是throw,使用throw可以主動(dòng)拋出一個(gè)異常??吹竭@你也許會(huì)一臉懵逼,主動(dòng)拋出???嫌異常不夠多,湊熱鬧不嫌事大??別急別急,中間一定有什么誤會(huì),把刀放下,有話好好說。
throw關(guān)鍵字確實(shí)是用來拋出異常的,你可以這樣使用:
public class Test { public static void main(String args[]){ try{ throw new NullPointerException("聽說你很閑,給你拋個(gè)異常。"); }catch (NullPointerException e) { System.out.println("這里捕獲空指針異常,提示內(nèi)容:" + e.getMessage()); e.printStackTrace(); } } }
輸出如下:
這里捕獲空指針異常,提示內(nèi)容:聽說你很閑,給你拋個(gè)異常。
java.lang.NullPointerException: 聽說你很閑,給你拋個(gè)異常。
at com.frank.chapter16.main.Test.main(Test.java:11)
用throw關(guān)鍵字可以拋出任意類型的異常,當(dāng)然,你想的話,還有拋Error,至于什么是Error,已經(jīng)跟Exception的關(guān)系,將在下一篇里進(jìn)行講解。暫時(shí)不用深究。
在throw異常的時(shí)候,可以加上拋出異常的原因,這樣可以更方便定位問題所在,當(dāng)然,一般來說不會(huì)像栗子中這樣使用的,這里只是為了簡(jiǎn)單起見。
到此為止,異常的上半篇已經(jīng)講解完畢,在這一篇里,說明了什么是異常,什么是異常處理,以及如何使用異常處理機(jī)制。相信大家對(duì)這個(gè)小妖精有了初步的認(rèn)識(shí),下一篇中,將會(huì)講解Exception家族都有哪些成員,如何使用自定義異常,已經(jīng)異常處理的實(shí)際使用中的正確姿勢(shì)。歡迎大家繼續(xù)關(guān)注,之后計(jì)劃每周兩篇以上的更新,如果有講解遺漏或者不好的地方,歡迎大家及時(shí)指出,共同進(jìn)步!
以上就是帶你了解Java中的異常處理(上)的詳細(xì)內(nèi)容,更多關(guān)于Java異常處理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java實(shí)現(xiàn)byte[]轉(zhuǎn)List的示例代碼
byte,即字節(jié),由8位的二進(jìn)制組成。在Java中,byte類型的數(shù)據(jù)是8位帶符號(hào)的二進(jìn)制數(shù)。List?是一個(gè)接口,它繼承于Collection的接口。它代表著有序的隊(duì)列。本文將介紹如何通過java實(shí)現(xiàn)byte[]轉(zhuǎn)List,需要的可以參考一下2022-01-01詳解Java動(dòng)態(tài)加載數(shù)據(jù)庫驅(qū)動(dòng)
本篇文章主要介紹了詳解Java動(dòng)態(tài)加載數(shù)據(jù)庫驅(qū)動(dòng),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05springboot 啟動(dòng)項(xiàng)目打印接口列表的實(shí)現(xiàn)
這篇文章主要介紹了springboot 啟動(dòng)項(xiàng)目打印接口列表的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09IKAnalyzer結(jié)合Lucene實(shí)現(xiàn)中文分詞(示例講解)
下面小編就為大家?guī)硪黄狪KAnalyzer結(jié)合Lucene實(shí)現(xiàn)中文分詞(示例講解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10在eclipse中使用SVN的實(shí)現(xiàn)方法(圖文教程)
這篇文章主要介紹了在eclipse中使用SVN的實(shí)現(xiàn)方法(圖文教程),文中通過圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07Java Swing組件布局管理器之FlowLayout(流式布局)入門教程
這篇文章主要介紹了Java Swing組件布局管理器之FlowLayout(流式布局),結(jié)合實(shí)例形式分析了Swing組件布局管理器FlowLayout流式布局的常用方法及相關(guān)使用技巧,需要的朋友可以參考下2017-11-11SWT(JFace) 文本編輯器 實(shí)現(xiàn)代碼
SWT(JFace) 文本編輯器 實(shí)現(xiàn)代碼2009-06-06Java下http下載文件客戶端和上傳文件客戶端實(shí)例代碼
這篇文章主要介紹了Java下http下載文件客戶端和上傳文件客戶端實(shí)例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-12-12