Part 3-1 Java 異常 2020-01-07

什么是異常:

1.異常字面翻譯就是“意外、例外”的意思,也就是非正常情況。

2.異常本質(zhì)上是程序上的錯誤。


程序中的異常:

1 .在編譯期間出現(xiàn)的錯誤有編譯器幫助我們一起修正,然而運行期間的錯誤便不是編譯器力所能及了,并且運行期間的錯誤往往是難以預料的。

2. 在程序運行過程中,意外發(fā)生的情況,背離我們程序本身的意圖的表現(xiàn),都可以理解為異常。

3. 當程序在運行期間出現(xiàn)了異常,如果置之不理,程序可能會不正常運行、強制中斷運行、造成用戶數(shù)據(jù)丟失、資源無法正常釋放、直接導致系統(tǒng)崩潰。

4. Java提供了異常機制來進行處理,通過異常機制,我們可以更好地提升程序的健壯性。


異常例子:

使用空的對象引用調(diào)用方法

String str = null;

System.out.println( str.length() );


數(shù)組訪問時下標越界

int[] ary={1,2,3};

for(int i=0;i<=3;i++){

? ? System.out.println(ary[i]);? }


算術運算時除數(shù)為0

int one= 12; int two=0;

System.out.println(one/two);


類型轉(zhuǎn)換時無法正常轉(zhuǎn)型

class Animal{}

class Dog extends Animal{}

class Cat extends Animal{}

public class Test{

????public static void main[String[] args]{

? ? ? ? Animal a1= new Dog();

? ?????? Animal a2= new Cat();

? ? ? ? Dog d1 = (Dog)a1;

? ? ? ? Dog d2 = (Dog)a2;

????}

}





異常的分類:


圖1.異常分類圖


Error:

? ? 1.我們編寫程序時不需要關心這類異常。

? ? 2.Error是程序無法處理的錯誤,大多數(shù)錯誤與代碼編寫者執(zhí)行的操作無關,表示是代碼運行時JVM(Java 虛擬機)出現(xiàn)的問題。

? ?3.這些錯誤是不可查的,因為它們在應用程序的控制和處理能力之外,而且絕大多數(shù)是程序運行時不允許出現(xiàn)的狀況。

? ?4.對于設計合理的應用程序來說,即使確實發(fā)生了錯誤,本質(zhì)上也不應該試圖去處理它所引起的異常狀況。


Exception:

? ? 1. Exception是程序本身可以處理的異常。異常處理經(jīng)常指針對這種異常的處理.

? ? 2. Exception類的異常包括 checked exception 和 uncheckedexception。


? ?unchecked exception

? ? ? ? 1. 編譯器不要求強制處置的異常。

? ? ? ? 2. 包含RuntimeException類及其子類異常。

? ? ? ? 3.? 如NullPointerException(空指針異常)、IndexOutOfBoundsException(下標越界異常)等,這些異常是unchecked exception 。

? ? ? ? 4.??Java編譯器不會檢查這些異常,在程序中可以選擇捕獲處理,也可以不處理,照樣正常編譯通過。


? ?checked exception

? ? ? ? 1. 編譯器要求必須處置的異常。

? ? ? ? 2.?是RuntimeException及其子類以外,其他的Exception類的子類。如IOException、SQLException等

? ? ? ? 3.?Java編譯器會檢查這些異常,當程序中可能出現(xiàn)這類異常時,要求必須進行異常處理,否則編譯不會通過。





異常處理:?拋出異常、捕捉異常

? ??異常總是先被拋出,后被捕捉的。

????對于可查異常必須捕捉、或者聲明拋出

? ??允許忽略:不可查的RuntimeException和Error。

拋出異常

? ? 1.當一個方法出現(xiàn)錯誤引發(fā)異常時,方法創(chuàng)建異常對象交付運行時系統(tǒng)。

? ? 2.異常對象中包括異常類型和異常出現(xiàn)的時程序狀態(tài)等異常信息。

? ? 3.運行時系統(tǒng)負責尋找處置異常的代碼并執(zhí)行


捕獲異常

? ? 1. 在方法拋出異常之后,運行時系統(tǒng)將轉(zhuǎn)為尋找合適的異常處理器。

? ? 2. 運行時系統(tǒng)從發(fā)生異常的方法開始,依次回查調(diào)用棧中的方法,當異常處理器所能處理的異常類型與方法拋出異常類型相符時,即合適的異常處理器。

? ? 3.?當運行時系統(tǒng)遍歷調(diào)用棧而未找到合適的異常處理器,則運行時系統(tǒng)終止。同時,意味著Java程序的終止。





處理實現(xiàn)

通過5個關鍵字來實現(xiàn):try、catch、 finally、throw、throws

捕獲:try,catch、 finally

? ? ? ? ? ?try:執(zhí)行可能執(zhí)行異常的代碼

? ? ? ? ? ?catch:捕獲異常

? ? ? ? ? ? finally:無論是否發(fā)生異常,代碼總能執(zhí)行

聲明:throws

? ? ? ? ? ? throws:聲明可能要拋出的異常

拋出:throw

????????????throw :手動拋出異常


?try-catch-finally


圖2.常規(guī)使用

? ??

try-catch( 有異常,能處理)

? ??

圖2.無finally有異常處理??


圖3. 處理流程


try-catch(?有異常,不能處理)


圖4.無finally有異常處理??


圖5.處理流程


try-catch( 無異常)


圖6.無finally無異常處理


圖7.處理流程





多重catch塊

????????1. 一旦某個catch捕獲到匹配的異常類型,將進入異常處理代碼。一經(jīng)處理結束,就意味著整個try-catch語句結束。其他的catch子句不再有匹配和捕獲異常類型的機會。

????????2.?對于有多個catch子句的異常程序而言,應該盡量將捕獲底層異常類的catch子句放在前面,同時盡量將捕獲相對高層的異常類的catch子句放在后面。否則,捕獲底層異常類的catch子句將可能會被屏蔽。

規(guī)則:

? ??????1.排列catch 語句的順序:先子類后父類。

? ??????2.發(fā)生異常時按順序逐個匹配。

????? ??3.只執(zhí)行第一個與異常類型匹配的catch語句。


圖8.多重catch


圖9.處理流程





try-catch-finally

1.?try塊后可以接零個或多個catch塊

2.?如果沒有catch,則必須跟一個finally塊

語法組合:

try-catch

try-finally

try-catch-finally

try-catch-catch-finally


圖9.?有finally有異常處理??


圖10.處理流程


實際應用中的經(jīng)驗與總結

????1. 處理運行時異常時,采用邏輯去合理規(guī)避同時輔助try-catch處理。

????2.?在多重catch塊后面,可以加一個catch(Exception)來處理可能會被遺漏的異常。

????3.?對于不確定的代碼,也可以加上try-catch,處理潛在的異常。

????4.?盡量去處理異常,切忌只是簡單的調(diào)用printStackTrace()去打印輸出。

????5.?具體如何處理異常,要根據(jù)不同的業(yè)務需求和異常類型去決定。

????6. 盡量添加finally語句塊去釋放占用的資源。


常見異常類型


圖11.常見類型表





throw & throws

? ??可以通過throws聲明將要拋出何種類型的異常,通過throw將產(chǎn)生的異常拋出。

throws:

? ??如果一個方法可能會出現(xiàn)異常,但沒有能力處理這種異常,可以在方法聲明處用throws子句來聲明拋出異常。方法將不對這些類型及其子類類型的異常作處理,而拋向調(diào)用該方法的方法,由他去處理。

? ?? 汽車在運行時可能會出現(xiàn)故障,汽車本身沒辦法處理這個故障, 那就讓開車的人來處理 。


????throws語句用在方法定義時聲明該方法要拋出的異常類型。

public void method() throws Exception1,Exception2,...,ExceptionN {

// 可能產(chǎn)生異常的代碼

}

使用規(guī)則:

? ????1. 如果是不可查異常(unchecked exception),即Error、RuntimeException或它們的子類,那么可以不使用throws關鍵字聲明要拋出的異常,編譯仍能順利通過,但在運行時會被系統(tǒng)拋出。


????????2. 如果一個方法中可能出現(xiàn)可查異常,要么用try-catch語句捕獲, 要么用throws子句聲明將它拋出,否則會導致編譯錯誤


????????3. 當拋出了異常,則該方法的調(diào)用者必須處理或者重新拋出該異常。

? ??????4. 當子類重寫父類拋出異常的方法,聲明的異常必須是父類方法所聲明異常的同類或子類。

throw:

? ??throw用來拋出一個異常。

? ? throw new IOException();?

????throw 拋出的只能夠是可拋出類Throwable 或者其子類的實例對象。

throw new String(“出錯啦”);?? 是錯誤的


圖12.使用情況1


圖13.使用情況2






自定義異常

1.使用Java內(nèi)置的異常類可以描述在編程時出現(xiàn)的大部分異常情況。

2.也可以通過自定義異常描述特定業(yè)務產(chǎn)生的異常類型。

3.所謂自定義異常,就是定義一個類,去繼承Throwable類或者? 它的子類。


圖14.范例






異常鏈


1.有時候我們會捕獲一個異常后再拋出另一個異常。

2.顧名思義就是:將異常發(fā)生的原因一個傳一個串起來,即把底層

的異常信息傳給上層,這樣逐層拋出。


圖15.范例

先進后出

圖16.產(chǎn)生的結果
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容