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