1.throw和throws
- 拋出異常有三種形式,一是throw,一個(gè)throws,還有一種系統(tǒng)自動(dòng)拋異常。
- 系統(tǒng)自動(dòng)拋出的異常
所有系統(tǒng)定義的編譯和運(yùn)行異常都可以由系統(tǒng)自動(dòng)拋出,稱為標(biāo)準(zhǔn)異常,并且 Java 強(qiáng)烈地要求應(yīng)用程序進(jìn)行完整的異常處理,給用戶友好的提示,或者修正后使程序繼續(xù)執(zhí)行。
- throw
throw是語(yǔ)句拋出的異常,一般在代碼塊內(nèi)部,當(dāng)程序出現(xiàn)某種邏輯錯(cuò)誤時(shí)由程序員主動(dòng)拋出某種特定類型的異常
throw(異常對(duì)象);
throw e;
- throws
throws是方法可能拋出異常的聲明(用在聲明方法時(shí),表示該方法可能要拋出異常,然后交給上層調(diào)用它的方法程序處理)
public void A (int a) throws Exception{...}
- throw和throws比較
throws出現(xiàn)在方法函數(shù)頭;而throw出現(xiàn)在函數(shù)體。
throws表示出現(xiàn)異常的一種可能性,并不一定會(huì)發(fā)生這些異常;throw則是拋出了異常,執(zhí)行throw則一定拋出了某種異常對(duì)象。
兩者都是消極處理異常的方式(這里的消極并不是說(shuō)這種方式不好),只是拋出或者可能拋出異常,但是不會(huì)由函數(shù)去處理異常,真正的處理異常由函數(shù)的上層調(diào)用處理。
- 編程習(xí)慣
在寫程序時(shí),對(duì)可能會(huì)出現(xiàn)異常的部分通常要用try{...}catch{...}去捕捉它并對(duì)它進(jìn)行處理;
用try{...}catch{...}捕捉了異常之后一定要對(duì)在catch{...}中對(duì)其進(jìn)行處理,那怕是最簡(jiǎn)單的一句輸出語(yǔ)句,或棧輸入e.printStackTrace();
如果是捕捉IO輸入輸出流中的異常,一定要在try{...}catch{...}后加finally{...}把輸入輸出流關(guān)閉;
如果在函數(shù)體內(nèi)用throw拋出了某種異常,最好要在函數(shù)名中加throws拋異常聲明,然后交給調(diào)用它的上層函數(shù)進(jìn)行處理。
2.final、finally和finalize
- final
final用來(lái)修飾屬性,方法和類
修飾屬性時(shí),表示屬性不可變,它只能指向初始時(shí)指向的的對(duì)象,本質(zhì)上,final修飾的是引用,對(duì)象不可改變,但是對(duì)象的內(nèi)容可以改變;
修飾方法時(shí),表示方法不可以被子類重寫,但是依然可以被子類引用;
修飾類時(shí),表示類不能被繼承,里面的方法不可以被重寫
- finally
finally作為異常處理的一部分,只能用于try/catch語(yǔ)句中,并且附帶一個(gè)語(yǔ)句塊,沒(méi)有意外情況,try/catch語(yǔ)句執(zhí)行,finally語(yǔ)句一定會(huì)執(zhí)行
- finalize
finalize是Object類的一個(gè)方法,當(dāng)gc執(zhí)行時(shí),會(huì)調(diào)用被回收對(duì)象的finalize()方法,可以覆蓋此方法實(shí)現(xiàn)對(duì)其他資源的回收。需要注意的是,一旦垃圾回收器準(zhǔn)備好釋放對(duì)象占用的空間,將首先調(diào)用其finalize()方法,并且在下一次垃圾回收發(fā)生時(shí),才會(huì)真正回收對(duì)象占用的內(nèi)存
3.try-catch-finally 中哪個(gè)部分可以省略
- catch-finally可以省略其中一個(gè),但catch和finally語(yǔ)句不能同時(shí)省略
try-catch
try-finally
try-catch-finally
4.當(dāng)try、catch中有return時(shí),finally中的代碼會(huì)執(zhí)行嗎
- 會(huì),不管有沒(méi)有異常,finally中的代碼都會(huì)執(zhí)行
1.當(dāng)try、catch中有return時(shí),finally中的代碼依然會(huì)繼續(xù)執(zhí)行
2.finally是在return后面的表達(dá)式運(yùn)算之后執(zhí)行的,此時(shí)并沒(méi)有返回運(yùn)算之后的值,而是把值保存起來(lái),不管finally對(duì)該值做任何的改變,返回的值都不會(huì)改變,依然返回保存起來(lái)的值。也就是說(shuō)方法的返回值是在finally運(yùn)算之前就確定了的。
3.如果return的數(shù)據(jù)是引用數(shù)據(jù)類型,而在finally中對(duì)該引用數(shù)據(jù)類型的屬性值的改變起作用,try中的return語(yǔ)句返回的就是在finally中改變后的該屬性的值。
4.finally代碼中最好不要包含return,程序會(huì)提前退出,也就是說(shuō)返回的值不是try或catch中的值
1.先執(zhí)行try中的語(yǔ)句,包括return后面的表達(dá)式,
2.有異常時(shí),先執(zhí)行catch中的語(yǔ)句,包括return后面的表達(dá)式,
3.然后執(zhí)行finally中的語(yǔ)句,如果finally里面有return語(yǔ)句,會(huì)提前退出
,最后執(zhí)行try中的return,有異常時(shí)執(zhí)行catch中的return。
4.在執(zhí)行try、catch中的return之前一定會(huì)執(zhí)行finally中的代碼(如果finally存在),如果finally中有return語(yǔ)句,就會(huì)直接執(zhí)行finally中的return方法,所以finally中的return語(yǔ)句一定會(huì)被執(zhí)行的。編譯器把finally中的return語(yǔ)句標(biāo)識(shí)為一個(gè)warning.
5.常見(jiàn)的異常類
- RuntimeException子類
| 序號(hào) | 異常名稱 | 異常描述 |
|---|---|---|
| 1 | java.lang.ArrayIndexOutOfBoundsException | 數(shù)組索引越界異常。當(dāng)對(duì)數(shù)組的索引值為負(fù)數(shù)或大于等于數(shù)組大小時(shí)拋出 |
| 2 | java.lang.ArithmeticException | 算術(shù)條件異常譬如:整數(shù)除零等。 |
| 3 | java.lang.SecurityException | 安全性異常 |
| 4 | java.lang.IllegalArgumentException | 非法參數(shù)異常 |
| 5 | java.lang.ArrayStoreException | 數(shù)組中包含不兼容的值拋出的異常 |
| 6 | java.lang.NegativeArraySizeException | 數(shù)組長(zhǎng)度為負(fù)異常 |
| 7 | java.lang.NullPointerException | 空指針異常。當(dāng)應(yīng)用試圖在要求使用對(duì)象的地方使用了null時(shí),拋出該異常。譬如:調(diào)用null對(duì)象的實(shí)例方法、訪問(wèn)null對(duì)象的屬性、計(jì)算null對(duì)象的長(zhǎng)度、使用throw語(yǔ)句拋出null等等。 |
- IOException
| 序號(hào) | 異常名稱 | 異常描述 |
|---|---|---|
| 1 | IOException | 操作輸入流和輸出流時(shí)可能出現(xiàn)的異常 |
| 2 | EOFException | 文件已結(jié)束異常 |
| 3 | FileNotFoundException | 文件未找到異常 |
- 其他
| 序號(hào) | 異常名稱 | 異常描述 |
|---|---|---|
| 1 | ClassCastException | 類型轉(zhuǎn)換異常類 |
| 2 | ArrayStoreException | 數(shù)組中包含不兼容的值拋出的異常 |
| 3 | SQLException | 操作數(shù)據(jù)庫(kù)異常類 |
| 4 | NoSuchFieldException | 字段未找到異常 |
| 5 | NoSuchMethodException | 方法未找到拋出的異常 |
| 6 | NumberFormatException | 字符串轉(zhuǎn)換為數(shù)字拋出的異常 |
| 7 | StringIndexOutOfBoundsException | 字符串索引超出范圍拋出的異常 |
| 8 | IllegalAccessException | 不允許訪問(wèn)某類異常 |
| 9 | InstantiationException | 當(dāng)應(yīng)用程序試圖使用Class類中的newInstance()方法創(chuàng)建一個(gè)類的實(shí)例,而指定的類對(duì)象無(wú)法被實(shí)例化時(shí),拋出該異常 |
| 10 | java.lang.ClassNotFoundException | 找不到類異常。當(dāng)應(yīng)用試圖根據(jù)字符串形式的類名構(gòu)造類,而在遍歷CLASSPAH之后找不到對(duì)應(yīng)名稱的class文件時(shí),拋出該異常。 |
6.異常
程序開(kāi)發(fā)和運(yùn)行過(guò)程中會(huì)出現(xiàn)
編譯錯(cuò)誤和運(yùn)行錯(cuò)誤。編譯錯(cuò)誤容易被發(fā)現(xiàn)并排除,而運(yùn)行錯(cuò)誤(邏輯錯(cuò)誤和異常)很難預(yù)料。因此為了程序的穩(wěn)定性和可靠性,就需要對(duì)程序異常處理和保護(hù)。
異常( Exception ):正常程序流程所不能處理或者沒(méi)有處理的異常情況或異常事件。
- Throwable
有兩個(gè)重要的子類:Exception(異常)和 Error(錯(cuò)誤),二者都是 Java 異常處理的重要子類,各自都包含大量子類。異常和錯(cuò)誤的區(qū)別是:異常能被程序本身可以處理,錯(cuò)誤是無(wú)法處理。
Error(錯(cuò)誤):是程序無(wú)法處理的錯(cuò)誤,表示運(yùn)行應(yīng)用程序中較嚴(yán)重問(wèn)題。
Exception(異常):是程序本身可以處理的異常。分兩大類:運(yùn)行時(shí)異常和非運(yùn)行時(shí)異常(編譯異常)。
非運(yùn)行時(shí)異常 (編譯異常):是RuntimeException以外的異常,類型上都屬于Exception類及其子類。從程序語(yǔ)法角度講是必須進(jìn)行處理的異常,如果不處理,程序就不能編譯通過(guò)。如IOException、SQLException等以及用戶自定義的Exception異常,一般情況下不自定義檢查異常
運(yùn)行時(shí)異常:都是RuntimeException類及其子類異常,如NullPointerException(空指針異常)、IndexOutOfBoundsException(下標(biāo)越界異常)等,這些異常是不檢查異常,程序中可以選擇捕獲處理,也可以不處理。
image.png
Java的異常(Throwable)分為可查的異常(checked exceptions)和不可查的異常(unchecked exceptions)。
可查異常(編譯器要求必須處置的異常):正確的程序在運(yùn)行中,很容易出現(xiàn)的、情理可容的異常狀況。除了Exception中的RuntimeException及RuntimeException的子類以外,其他的Exception類及其子類(例如:IOException和ClassNotFoundException)都屬于可查異常。這種異常的特點(diǎn)是Java編譯器會(huì)檢查它,也就是說(shuō),當(dāng)程序中可能出現(xiàn)這類異常,要么用try-catch語(yǔ)句捕獲它,要么用throws子句聲明拋出它,否則編譯不會(huì)通過(guò)。
不可查異常(編譯器不要求強(qiáng)制處置的異常):包括運(yùn)行時(shí)異常(RuntimeException與其子類)和錯(cuò)誤(Error)。RuntimeException表示編譯器不會(huì)檢查程序是否對(duì)RuntimeException作了處理,在程序中不必捕獲RuntimException類型的異常,也不必在方法體聲明拋出RuntimeException類。RuntimeException發(fā)生的時(shí)候,表示程序中出現(xiàn)了編程錯(cuò)誤,所以應(yīng)該找出錯(cuò)誤修改程序,而不是去捕獲RuntimeException。
異常處理機(jī)制
在 Java 應(yīng)用程序中,異常處理機(jī)制為:拋出異常,捕捉異常。
拋出異常:throw和throws
捕捉異常:try/catch/finally語(yǔ)句
