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