好程式員Java教程分享Java系列之異常定義
異常定義
異常:就是程式在運作的過程中遇到的種種不正常的情況。
特點:如果一個程式在運作中遇到了一個未經處理的異常,則這個異常會終止程式的運作。
但是如果程式出現的異常被處理了,此時程式不會被終止。是以我們需要知道怎麼去處理異常。
其實在Java中,異常也是一個類。
類的體系:
異常的分類:可以分成兩種異常:
- Throwable: 是所有的異常的根類
- Error: 發生在編譯器級别的,我們程式無法處理的錯誤。
- Exception: 我們可以去處理的異常。
- RuntimeException:
- 運作時異常(Runtime Exception)
- 發生在程式運作的過程中的異常。
- 如果不處理這種異常,程式可以正常編譯,但是當執行到異常産生的時候,會終止程式的運作。
- 例如:NullPointerException、IndexOutOfBoundsException、ArithmeticException...
- 非運作時異常(Non-Runtime Exception)
- 發生在程式編譯的過程中的異常。(編譯時異常)
- 如果不處理這種異常,程式将無法進行編譯。
- 例如:ParseException...
常用結構
需要使用文法:try-catch-finally
文法:
try {
// 這裡寫可能會産生異常的代碼。
// 注意:
// 一旦這裡面的代碼産生了異常,從異常産生開始往後所有try中的代碼都不再執行,直接執行指定的catch
}
catch(需要捕獲的異常類型 辨別符) {
// 捕獲異常,如果try中産生的異常類型和我們要捕獲的異常類型比對,此時會執行這個代碼段中的内容
// 如果執行到這裡了,相當于這個異常被捕獲、處理了,這個異常将不再終止程式的運作。
finally {
// 這裡的代碼始終會執行。
// 無論try中的代碼有沒有異常産生,這裡的代碼都會執行。
// 在這裡我們一般情況下是做一些資源釋放的工作。
備注:
- 以上,是完整的try-catch-finally語句。但是實際在用的時候,try後面可以隻有catch, 也可隻有finally,但是不能什麼都沒有。
- 一般情況下,catch我們是不會省略不寫的。
- 如果try中的代碼可能産生的異常不止一種
- 如果需要對産生的不同異常進行不同的處理,可以使用多個catch語句
- 多個catch語句的先後順序
- 如果多個catch中的異常,沒有繼承關系,則先後順序沒有影響
- 如果多個catch中的異常,有繼承關系,則子類異常在前,父類異常在後
- 如果需要對某些異常做同樣的處理,可以在同一個catch中,用 | 拼接所有要處理的異常。
- 這些用|拼接起來的異常之間,不能有繼承關系
- 如果需要對所有的異常做同樣的處理,可以在一個catch中捕獲一個父類異常。
public static int show(int a, int b) { int c = 0; try { c = a / b; // 能走到這裡,說明上面的除沒有異常。 return c; } catch (ArithmeticException e) { System.out.println("出現了一個算術異常"); return c; } finally { // 在return之前,執行finally中的代碼段 System.out.println("finally中的代碼執行了"); c = -10; } }
以上代碼段,在try和catch中都有return語句。
finally中的代碼始終會執行,但是針對這種情況,他的執行時機:
先執行return語句,此時,将需要傳回的值緩存起來。然後再去執行finally語句中的代碼,執行結束後,傳回剛才緩存的那個值。
finally關鍵字的應用
throw和throws關鍵字
throw:
常用在某一個方法中,表示抛出一個異常對象。等在調用這個方法的時候去處理這個異常。
一個異常對象被執行個體化完成後,不具備任何意義。隻有被throw關鍵字抛出了,才具備異常的功能。
throws:
注意:在方法重寫中
- 常用在方法的聲明部分,用來描述這個方法可能會抛出什麼異常,給調用這個方法的部分看的。
- 如果在方法中使用throw抛出了一個Runtime Exception:
- throws可以寫,也可以不寫
- 備注:一般情況下,我們還是會按照實際情況進行描述的。
- 如果在方法中使用throw抛出了一個Non-Runtime Exception:
- 此時throws必須寫
- 可以在方法中不去處理異常,将異常處理提到調用這個方法的時候。
- 如果重寫的方法抛出的是一個Non-Runtime Exception
- 子類方法抛出的異常需要父類方法抛出異常的子類型,或者等同于父類方法抛出的異常類型
- 不能讓子類重寫的方法抛出異常的類型高于父類方法抛出的異常類型
自定義異常
系統給我們提供了很多的異常類,但是這些異常類并不能夠滿足我們所有的需求。這種情況下,我們就需要去自定義異常。繼承自異常類,寫一個子類即可。在自定義異常類的時候,類名最好使用Exception作為結尾
- 自定義RuntimeException
- 繼承自RuntimeException類,寫一個子類。這個子類異常就是一個運作時異常。
class NumberOfLegException extends RuntimeException { /** * 通過一個異常描述資訊來執行個體化一個異常對象 * @param message */ public NumberOfLegException(String message) { // 怎麼樣去設定這個異常資訊? super(message); } }
- 自定義Non-Runtime Exception
- 繼承自Exception類,寫一個子類。這個子類異常就是一個非運作時異常。
class NumberOfLegException extends Exception { /** * 通過一個異常描述資訊來執行個體化一個異常對象 * @param message */ public NumberOfLegException(String message) { // 怎麼樣去設定這個異常資訊? super(message); } }