顧名思義,通俗來說異常就是指,那些產生在我們本來斟酌和設定的計劃以外的意外情況。
生活中總是會存在各種突發情況,如果沒有做好準備,就讓人措手不及。
你和朋友約好了明天1起去登山,半道上忽然烏云蔽日,下起了磅礴大雨。這就是所謂的異常情況。
你1下子傻眼了,然后看見朋友淡定的從背包里取出1件雨衣穿上,淫笑著看著你。這就是對異常的處理。
對1個OO程序猿來說,所做的工作就是:將需要處理的現實生活中的復雜問題,抽象出來編寫成為程序。
既然現實生活中總是存在著各種突然的異常情況,那末對應其抽象出的代碼,自然也是存在這樣的風險的。
所以常常說:要編寫1個完善的程序其實不只是簡簡單單的把功能實現,還要讓程序具有處理在運行中可能出現的各種意外情況的能力。
這就是所謂的異常的使用。
這就是Java當中異常體系的結構構成,從圖中我們可以提取到的信息就是:
1、Java中定義的所有異常類都是內置類Throwable的子類。
2、Java中的異常通常被分為兩大類:Error和Exception:
3、Exception最多見的兩種異常類型分別是:
要理解Java中的異常使用,首先要明白幾個關于異常處理的工具 - 異常處理關鍵字的使用。
1、throw:用以在方法內部拋出指定類型的異常。
2、throws:用以聲明 1個方法可能產生的異常(通常都是編譯時檢測異常)有哪些。
用try語句塊包括可能產生異常的代碼,catch用于捕獲產生的異常,并在catch語句塊中定義對捕獲到的異常的處理方式。
特點是被try語句塊包括的內容中,是不是真的產生了異常。程序終究都將履行finally語句塊當中的內容。
通經常使用于對資源的釋放操作,例如:通過JDBC連接數據庫等情況。
了解Java中異常類的實際利用之前,應當先了解兩個概念,用以對最經常使用的異常做1個分類:
1、編譯時被檢測異常:
只要是Exception和其子類都是,除特殊子類RuntimeException體系。
所謂的編譯時被檢測異常也就是指在程序的編譯器就會進行檢測的異常分類。
也就是說,如果1個方法拋出了1個編譯時檢測異常,Java則要求我們必須進行處理。
既:通過throws對異常進行聲明處理 或是 通過try-catch對異常進行捕獲處理。
如果程序編譯時檢測到該類異常沒有被進行任何處理,那末編譯器則會報出1個編譯毛病。
上面代碼中的ClassNotFoundException就是1種編譯時檢測異常,這個異常是由Class類當中的forName方法所拋出并聲明的。
如果我們在使用該方法時沒有對異常進行處理:聲明或捕獲,那末該程序就會編譯失敗。
通過這個例子想要說明的是:編譯時被檢測異常通常都是指那些“可以被我們預感”的異常情況。
正例如:我們通過Class.forName是想要獲得指定類的字節碼文件對象,所以我們自然也能夠預感可能會存在:
與我們傳入的類名參數所對應的類字節碼文件對象不存在,查找不到的情況。
既然這類意外情況是可以被預感的,那自然就應當針對其制定1些應對方案。
2、編譯時不檢測異常(運行時異常):
就是指Exception下的子類RuntimeException和其子類。
通常這類問題的產生,會致使程序功能沒法繼續、運算沒法進行等情況產生;
但這類異常更多是由于調用者的緣由或引發了內部狀態的改變而致使的。
所以針對這類異常,編譯器不要求我們處理,可以直接編譯通過。
而在運行時,讓調用者調用時的程序強迫停止,從而讓調用者對本身的代碼進行修正。
曾看到過1道面試題:列出你實際開發中最多見的5個運行時異常,就我自己而言,如果硬要說出5個,那多是:
NullPointerException(空指針異常)、IndexOutOfBoundsException(角標越界異常)、ArithmeticException(異常運算條件異常)
ClassCastException(類型轉換異常)、IllegalArgumentException(非法參數異常)
同時也能夠看到,雖然“division”方法可能引發異常,但由于是運行時異常,所以即便不做任何異常處理,程序任然能夠通過編譯。
但當該類型的異常真的產生的時候,調用者運行的程序就會直接停止運行,并輸出相干的異常信息。
通過自定義異常理解檢測異常和非檢測異常
前面我們說到的都是Java本身已封裝好提供給我們的1些異常類。由此我們可以看到,秉持于“萬物皆對象”的思想,Java中的異常實際上也是1種對象。
所以自然的,除Java本身提供的異常類以外,我們也能夠根據自己的需求定義自己的異常類。
這里我想通過比較有趣的簡單的自定義異常,結合自己的理解,總結1下Java當中檢測異常和非檢測異常的使用。
1、編譯時檢測異常
對編譯時異常,我的理解就是:所有你可以預感、并且能夠做出應對的意外狀態,都應當通過編譯時檢測異常的定義的方式進行處理。
舉個例子來講:假定我們開了1家小餐館,除開正常營業的流程以外。自然可能產生1些意外狀態,例如:
菜里不謹慎出現了蟲子,出現了頭發;或是餐館突然停電之類的狀態。這些狀態是每一個經營餐館的人事前都應當斟酌到的情況。
既然我們已斟酌到了這些意外情況產生的可能性,那末自然就應當針對這些狀態做出應對的方案。所以代碼多是這樣的:
1、首先,定義兩個編譯時檢測異常類,菜品異常和停電異常:
2、然后我們在餐廳類當中的營業方法當中做出了聲明,如果出現“菜里有蟲”或“菜里有頭發的問題”,我們就用thorw拋出1個菜品異常;如果“停電”,就拋出停電異常。
3、但是,由于我們拋出這1類異常是由于想告知餐廳的相干人員,在餐廳營業后,可能會出現這些意外情況。所以還應當通過throws告知他們:營業可能會出現這些意外情況。
4、餐廳相干人員接到了聲明。因而制定了方案,當餐廳開始營業后。如果出現了菜品異常,請為客人換1盤菜或退款;如果出現停電異常,請啟動店里自備的發機電。
2、運行時異常
對運行時異常的使用,我個人覺得最經常使用的情況有兩種:
第1、編譯時檢測異經常使用于定義那些我們可以提供“友好的解決方案”的情況。那末針對另外1些狀態,多是我們沒法很好的進行解決的。
遇到這類情況,我們可能希望采取1些“強迫手段”,那就是直接讓你的程序停止運行。這時候,就能夠使用運行時異常。
第2、如果對異常處理后,又引發1連串的毛病的“連鎖反應”的時候。
我們先來看1下第1種使用使用情況是怎樣樣的。例如說:
我們在上面的餐廳的例子中,餐廳即便出現菜品異常或停電異常這1類意外情況。
但針對這1類的意外情況,我們是能夠提供較為妥善的解決方案的。
而通過我們提供的針對這些異常情況的解決方案進行處理以后,餐廳照舊營業,顧客接著用餐(程序照舊能夠正常運行)。
但還有1種情況,可能不管我們怎樣樣友好的嘗試進行解決,都難以讓顧客滿意。這類顧客就是傳說中被稱為“砸場子”的顧客。
針對這類情況,我們可能就要采取更加“強硬的措施”了。例如直接報警把他帶走(不讓程序繼續運行了),這就是所謂的運行時異常:
可以看到出現該運行時異常,程序將直接被終止運行,砸場子的人直接被警察帶走了。
那末接下來,我們就能夠來看看第2種使用情況了,甚么是所謂的“引發連鎖效應的毛病”。
舉個例子來講,以我們上面用到的“被除數為0”的異常情況。你可能會思考:傳入的被除數為0,這樣的情況我們是可以斟酌到的。
并且我們也能夠針對這樣的毛病給出對應的措施。那Java為何不將這樣的異常定義為編譯時檢測異常呢?
那末我無妨假定ArithmeticException就是編譯時檢測異常,所以我們必須對其作出處理,那末可能出現這樣的代碼:
如果傳入的被除數為0,就返回負數“⑴”,“⑴”就代表這個運算出錯了。
因而這時候有1個調用者,恰好調用了我們的除法運算方法計算“5除以0的結果”,天經地義的,他得到的結果為:
“5除以0的結果為⑴”。好了,這下叼了,這哥們立馬拿著這個運算結果,去向他的朋友夸耀:
你們都是2B吧,算不出5除以0等于多少是吧?告知你們,等于⑴。因而,在朋友的眼中,他成2B了。
上一篇 EasyUI表單元素總結
下一篇 JSP1.x 自定義標簽