初識(shí)異常(Exception)
-
比如我們?cè)谌?shù)組里面的某個(gè)值得時(shí)候,經(jīng)常會(huì)出現(xiàn)定義的取值范圍超過了數(shù)組的大小,那么運(yùn)行的時(shí)候JVM就會(huì)發(fā)出異常提示。
-
再比如我們要處理的數(shù)據(jù)超出了系統(tǒng)數(shù)據(jù)類型表示范圍時(shí)了罪,由操作系統(tǒng)發(fā)出的Error提示。
發(fā)生異常的原因有很多端仰,但是通常有以下幾大類:輸入了違法的數(shù)據(jù)捶惜、找不到要打開的文件、網(wǎng)絡(luò)通信中斷荔烧、JVM內(nèi)存溢出吱七。
Java異常類層次
Java是通過Throwable類的所有子類來描述各種異常汽久。所有異常的老祖宗都是Throwable。
Throwable
Throwable 類是所有錯(cuò)誤或異常的超類踊餐。只有當(dāng)對(duì)象是此類(或其子類之一)的實(shí)例時(shí)景醇,才能通過 Java 虛擬機(jī)或者 Java throw 語句拋出。類似地吝岭,只有此類或其子類之一才可以是 catch 中的參數(shù)類型三痰。Throwable類有兩個(gè)重要的子類:Exception(異常)和 Error(錯(cuò)誤)。
Error
Java程序通常不捕獲錯(cuò)誤窜管,出現(xiàn)錯(cuò)誤一般都出現(xiàn)了比較嚴(yán)重的故障散劫,此時(shí)程序已經(jīng)無法處理了,然后在控制臺(tái)通知你幕帆,我已經(jīng)歇菜了获搏。大多數(shù)錯(cuò)誤與程序的執(zhí)行操作無關(guān),而是程序運(yùn)行時(shí)失乾,JVM出了問題常熙,如系統(tǒng)崩潰,虛擬機(jī)錯(cuò)誤碱茁,內(nèi)存空間不足等裸卫。這些錯(cuò)誤,僅靠程序本身無法恢復(fù)和和預(yù)防纽竣,遇到這樣的錯(cuò)誤墓贿,建議讓程序終止。
Exception
Exception類表示程序可以處理的異常蜓氨,是可以捕獲且可能恢復(fù)的募壕。遇到這類異常,應(yīng)該盡可能處理異常语盈,使程序恢復(fù)運(yùn)行,而不應(yīng)該隨意終止異常缰泡。通常刀荒,Java的異常(包括Exception和Error)分為可查的異常(checked exceptions)和不可查的異常(unchecked exceptions)。
可查異常棘钞、不可查異常
可查異常(編譯器要求必須處置的異常):指程序在運(yùn)行中缠借,很容易出現(xiàn)的、情理可容的異常狀況宜猜∑梅担可查異常雖然是異常狀況,但在一定程度上它的發(fā)生是可以預(yù)計(jì)的姨拥,而且一旦發(fā)生這種異常狀況绅喉,就必須采取某種方式進(jìn)行處理渠鸽。
除了RuntimeException及其子類以外,其他的Exception類及其子類都屬于可查異常柴罐。這種異常的特點(diǎn)是Java編譯器會(huì)檢查它徽缚,也就是說,當(dāng)程序中可能出現(xiàn)這類異常革屠,要么用try-catch語句捕獲它凿试,要么用throws子句聲明拋出它,否則編譯不會(huì)通過似芝。不可查異常(編譯器不要求強(qiáng)制處置的異常):包括運(yùn)行時(shí)異常(RuntimeException與其子類)和錯(cuò)誤(Error)那婉。
運(yùn)行時(shí)異常RuntimeException 是可能被程序員避免的異常。它是Exception的一個(gè)重要子類党瓮,是那些可能在 Java 虛擬機(jī)正常運(yùn)行期間拋出的異常的超類详炬。例如:ArithmeticException,一個(gè)整數(shù)“除以零”時(shí)會(huì)拋出此異常麻诀;ArrayStoreException痕寓,試圖將錯(cuò)誤類型的對(duì)象存儲(chǔ)到一個(gè)對(duì)象數(shù)組時(shí)拋出此異常;IndexOutOfBoundsException蝇闭,表示某排序索引(例如對(duì)數(shù)組呻率、字符串排序)超出范圍時(shí)拋出此異常;NullPointerException呻引,當(dāng)應(yīng)用程序試圖在需要對(duì)象的地方使用 null 時(shí)拋出該異常礼仗。這些異常都是不檢查異常,程序中可以選擇捕獲處理逻悠,也可以不處理元践。運(yùn)行時(shí)異常的特點(diǎn)是Java編譯器不會(huì)檢查它,也就是說童谒,當(dāng)程序中可能出現(xiàn)這類異常单旁,即使沒有用try-catch語句捕獲它,也沒有用throws子句聲明拋出它饥伊,也會(huì)編譯通過象浑。
異常方法
下面的列表是 Throwable 類的主要方法:
異常處理機(jī)制
在 Java 應(yīng)用程序中,異常處理機(jī)制為:拋出異常琅豆,捕捉異常愉豺。異常總是先被拋出茫因,后被捕捉的蚪拦。
-
拋出異常:當(dāng)一個(gè)方法出現(xiàn)錯(cuò)誤引發(fā)異常時(shí),方法創(chuàng)建異常對(duì)象并交付運(yùn)行時(shí)系統(tǒng),異常對(duì)象中包含了異常類型和異常出現(xiàn)時(shí)的程序狀態(tài)等異常信息驰贷。運(yùn)行時(shí)系統(tǒng)負(fù)責(zé)尋找處置異常的代碼并執(zhí)行盛嘿。
注意:
對(duì)于運(yùn)行時(shí)異常、錯(cuò)誤或可查異常饱苟,Java技術(shù)所要求的異常處理方式有所不同孩擂。
① 由于運(yùn)行時(shí)異常的不可查性,為了更合理箱熬、更容易地實(shí)現(xiàn)應(yīng)用程序类垦,Java規(guī)定,運(yùn)行時(shí)異常將由Java運(yùn)行時(shí)系統(tǒng)自動(dòng)拋出城须,允許應(yīng)用程序忽略運(yùn)行時(shí)異常蚤认。對(duì)于方法運(yùn)行中可能出現(xiàn)的Error猖辫,當(dāng)運(yùn)行方法不欲捕捉時(shí)蚜迅,Java允許該方法不做任何拋出聲明度秘。因?yàn)楣兀蠖鄶?shù)Error異常屬于永遠(yuǎn)不能被允許發(fā)生的狀況,也屬于合理的應(yīng)用程序不該捕捉的異常瘫想。
② 對(duì)于所有的可查異常昧谊,Java規(guī)定:一個(gè)方法必須捕捉玫霎,或者聲明拋出方法之外褥蚯。也就是說挚冤,當(dāng)一個(gè)方法選擇不捕捉可查異常時(shí),它必須聲明將拋出異常赞庶。
代碼示例
① throws語句用在方法定義時(shí)聲明該方法要拋出的異常類型训挡,如果拋出的是Exception異常類型,則該方法被聲明為拋出所有的異常歧强。
② 當(dāng)方法拋出異常列表的異常時(shí)澜薄,方法將不對(duì)這些類型及其子類類型的異常作處理,而拋向調(diào)用該方法的方法摊册,如果調(diào)用者不想處理該異常肤京,可以繼續(xù)向上拋出,但最終要有能夠處理該異常的調(diào)用者茅特。
③ throw總是出現(xiàn)在函數(shù)體中蟆沫,用來拋出一個(gè)Throwable類型的異常。程序會(huì)在throw語句后立即終止温治,它后面的語句執(zhí)行不到。
public class ClassName
{
public void named(String string) throws RemoteException
{
// Method implementation
throw new RemoteException();
}
//Remainder of class definition
}
一個(gè)方法可以聲明拋出多個(gè)異常戒悠,多個(gè)異常之間用逗號(hào)隔開熬荆。
public class ClassName
{
public void withdraw(double amount) throws RemoteException, InsufficientFundsException
{
// Method implementation
}
//Remainder of class definition
}
-
捕獲異常:使用 try 和 catch 關(guān)鍵字可以捕獲異常。try/catch 代碼塊放在異吵窈可能發(fā)生的地方卤恳。
語法
try
{
// 程序代碼
}catch(ExceptionName e)
{
//Catch 塊
}
當(dāng)try內(nèi)的監(jiān)控區(qū)域發(fā)生異常累盗,就會(huì)匹配后面的catch塊。Java方法在運(yùn)行過程中出現(xiàn)異常突琳,則創(chuàng)建異常對(duì)象若债。將異常拋出監(jiān)控區(qū)域之外,由Java運(yùn)行時(shí)系統(tǒng)試圖尋找匹配的catch子句以捕獲異常拆融。若有匹配的catch子句蠢琳,則運(yùn)行其異常處理代碼,try-catch語句結(jié)束镜豹。
匹配的原則是:如果拋出的異常對(duì)象屬于catch塊的異常類傲须,或者屬于該異常類的子類,則認(rèn)為生成的異常對(duì)象與catch塊捕獲的異常類型相匹配趟脂。
try/catch 實(shí)例:
public class Test{
public static void main(String args[]){
try{
int a[] = new int[2];
System.out.println("輸出數(shù)組 :" + a[3]);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("拋出異常 :" + e);
}
}
}
多重捕獲塊:
try{
// 程序代碼
}catch(異常類型1 異常的變量名1){
// 程序代碼
}catch(異常類型2 異常的變量名2){
// 程序代碼
}catch(異常類型2 異常的變量名2){
// 程序代碼
}
如果監(jiān)控區(qū)域發(fā)生異常泰讽,異常被拋給第一個(gè) catch 塊。如果拋出異常的數(shù)據(jù)類型與 ExceptionType1 匹配昔期,它在這里就會(huì)被捕獲已卸。如果不匹配,它會(huì)被傳遞給第二個(gè) catch 塊硼一。如此累澡,直到異常被捕獲或者通過所有的 catch 塊。
多重捕獲塊實(shí)例:
public class TestException {
public static void main(String[] args) {
int[] intArray = new int[3];
try {
for (int i = 0; i <= intArray.length; i++) {
intArray[i] = i;
System.out.println("intArray[" + i + "] = " + intArray[i]);
System.out.println("intArray[" + i + "]模 " + (i - 2) + "的值: "
+ intArray[i] % (i - 2));
}
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("intArray數(shù)組下標(biāo)越界異常欠动。");
} catch (ArithmeticException e) {
System.out.println("除數(shù)為0異常永乌。");
}
System.out.println("程序正常結(jié)束。");
}
}
//intArray[0] = 0
//intArray[0]模 -2的值: 0
//intArray[1] = 1
//intArray[1]模 -1的值: 0
//intArray[2] = 2
//除數(shù)為0異常具伍。
//程序正常結(jié)束翅雏。
注意:一旦某個(gè)catch捕獲到匹配的異常類型,將進(jìn)入異常處理代碼人芽。一經(jīng)處理結(jié)束望几,就意味著整個(gè)try-catch語句結(jié)束。其他的catch子句不再有匹配和捕獲異常類型的機(jī)會(huì)萤厅。
finally關(guān)鍵字
① 無論是否發(fā)生異常橄抹,finally 代碼塊中的代碼總會(huì)被執(zhí)行。
② 在 finally 代碼塊中惕味,可以運(yùn)行清理類型等收尾善后性質(zhì)的語句楼誓。
③ finally 代碼塊出現(xiàn)在 catch 代碼塊最后。
④ finally中使用return是一種很不好的編程風(fēng)格名挥,它會(huì)覆蓋掉所有的其它返回疟羹,并且吃掉catch中拋出的異常。
語法如下:
try{
// 程序代碼
}catch(異常類型1 異常的變量名1){
// 程序代碼
}catch(異常類型2 異常的變量名2){
// 程序代碼
}finally{
// 程序代碼
}
代碼實(shí)例:
public class ExcepTest{
public static void main(String args[]){
int a[] = new int[2];
try{
System.out.println("Access element three :" + a[3]);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("Exception thrown :" + e);
}
finally{
a[0] = 6;
System.out.println("First element value: " +a[0]);
System.out.println("The finally statement is executed");
}
}
}
//Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3
//First element value: 6
//The finally statement is executed
注意:當(dāng)在try塊或catch塊中遇到return語句時(shí),finally語句塊將在方法返回之前被執(zhí)行榄融。在finally語句塊中發(fā)生了異常参淫,finally塊不會(huì)被執(zhí)行。
try-catch-finally執(zhí)行順序
1)當(dāng)try沒有捕獲到異常時(shí):try語句塊中的語句逐一被執(zhí)行愧杯,程序?qū)⑻^catch語句塊涎才,執(zhí)行finally語句塊和其后的語句;
2)當(dāng)try捕獲到異常力九,catch語句塊里沒有處理此異常的情況:當(dāng)try語句塊里的某條語句出現(xiàn)異常時(shí)耍铜,而沒有處理此異常的catch語句塊時(shí),此異常將會(huì)拋給JVM處理畏邢,finally語句塊里的語句還是會(huì)被執(zhí)行业扒,但finally語句塊后的語句不會(huì)被執(zhí)行;
3)當(dāng)try捕獲到異常舒萎,catch語句塊里有處理此異常的情況:在try語句塊中是按照順序來執(zhí)行的程储,當(dāng)執(zhí)行到某一條語句出現(xiàn)異常時(shí),程序?qū)⑻絚atch語句塊臂寝,并與catch語句塊逐一匹配章鲤,找到與之對(duì)應(yīng)的處理程序,其他的catch語句塊將不會(huì)被執(zhí)行咆贬,而try語句塊中败徊,出現(xiàn)異常之后的語句也不會(huì)被執(zhí)行,catch語句塊執(zhí)行完后掏缎,執(zhí)行finally語句塊里的語句皱蹦,最后執(zhí)行finally語句塊后的語句;
自定義異常
import java.lang.Exception;
public class TestException {
static int quotient(int x, int y) throws MyException { // 定義方法拋出異常
if (y < 0) { // 判斷參數(shù)是否小于0
throw new MyException("除數(shù)不能是負(fù)數(shù)"); // 異常信息
}
return x/y; // 返回值
}
public static void main(String args[]) { // 主方法
int a =3;
int b =0;
try { // try語句包含可能發(fā)生異常的語句
int result = quotient(a, b); // 調(diào)用方法quotient()
} catch (MyException e) { // 處理自定義異常
System.out.println(e.getMessage()); // 輸出異常信息
} catch (ArithmeticException e) { // 處理ArithmeticException異常
System.out.println("除數(shù)不能為0"); // 輸出提示信息
} catch (Exception e) { // 處理其他異常
System.out.println("程序發(fā)生了其他的異常"); // 輸出提示信息
}
}
}
class MyException extends Exception { // 創(chuàng)建自定義異常類
String message; // 定義String類型變量
public MyException(String ErrorMessagr) { // 父類方法
message = ErrorMessagr;
}
public String getMessage() { // 覆蓋getMessage()方法
return message;
}
}
注意
子類重寫父類的方法的時(shí)候眷蜈,如果父類沒有異常沪哺,那么子類也不允許在重寫的方法拋出異常有異常。也就是說父類沒有拋出異常酌儒,那么子類也不可以辜妓。
寫完嘍!ㄟ(▔,▔)ㄏㄟ(▔,▔)ㄏㄟ(▔,▔)ㄏ
知識(shí)重在總結(jié)和梳理忌怎,只有不斷地去學(xué)習(xí)并運(yùn)用籍滴,才能化為自己的東西。當(dāng)你能為別人講明白的時(shí)候榴啸,說明自己已經(jīng)掌握了孽惰。
歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處鸥印!
如果有錯(cuò)誤的地方勋功,或者有您的見解腥例,還請(qǐng)不嗇賜教!
喜歡的話酝润,麻煩點(diǎn)個(gè)贊!
本文轉(zhuǎn)載自:http://blog.csdn.net/hguisu/article/details/6155636
l