什么是異常
異常是指阻止當(dāng)前方法或者作用域繼續(xù)執(zhí)行的問題潮改。異常對象(包括Exception和Error)都是Throwable的子類對象,都具有可拋性。不同的是凝果,Exception是JVM發(fā)出的異常提示,可以進行處理睦尽;Error是由操作系統(tǒng)發(fā)出的異常提示器净,一旦出現(xiàn)Error,必須修改源代碼骂删。
異常處理機制
在 Java 中掌动,異常處理機制有兩種,分別為拋出異常和捕獲異常宁玫。
拋出異常
當(dāng)一個方法出現(xiàn)錯誤引發(fā)異常時粗恢,方法創(chuàng)建異常對象并交付運行時系統(tǒng),異常對象中包含了異常類型和異常出現(xiàn)時的程序狀態(tài)等異常信息欧瘪。運行時系統(tǒng)負(fù)責(zé)尋找處置異常的代碼并執(zhí)行眷射。
捕獲異常
在方法拋出異常之后,運行時系統(tǒng)將轉(zhuǎn)為尋找合適的異常處理器(exception handler)。潛在的異常處理器是異常發(fā)生時依次存留在調(diào)用棧中的方法的集合妖碉。當(dāng)異常處理器所能處理的異常類型與方法拋出的異常類型相符時涌庭,即為合適 的異常處理器。運行時系統(tǒng)從發(fā)生異常的方法開始欧宜,依次回查調(diào)用棧中的方法坐榆,直至找到含有合適異常處理器的方法并執(zhí)行。當(dāng)運行時系統(tǒng)遍歷調(diào)用棧而未找到合適 的異常處理器冗茸,則運行時系統(tǒng)終止席镀。同時,意味著Java程序的終止夏漱。
異常的體系介紹
(圖片來自度娘)
Java作為一門面向?qū)ο蟮恼Z言豪诲,異常也被當(dāng)做對象來處理。
Throwable 類是所有異常類的根類挂绰,它有兩個子類 Error 類和 Exception屎篱。
Error 類是所有 error 類型的父類,子類有 VirtualMachineError 和 IOError葵蒂。
Exception 類是所有 exception 類型的父類交播,子類大致分為:RuntimeException(NullPointerException、IndexOutOfBoundsException刹勃、IllegalArgumentException等) 和 非 RuntimeException(IOException堪侯、SQLException等)。
異常的處理方式
對于 Error 我們是沒有辦法處理的荔仁,只能改錯誤的代碼伍宦。而對于 Exception 我們可以使用 throws 關(guān)鍵詞拋出方法可能產(chǎn)生的異常,然后在調(diào)用方法時使用 try-catch 語句捕獲拋出的異常并進行相應(yīng)的處理乏梁。
例1:
我們先運行如下代碼:
public class Main {
public static void main(String[] args) {
div(4, 0);
System.out.println("執(zhí)行可能存在問題的代碼");
}
public static int div(int a, int b) {
return a / b;
}
}
結(jié)果如下:
Exception in thread "main"
java.lang.ArithmeticException: / by zero
at com.xxx.Main.div(Main.java:11)
at com.xxx.Main.main(Main.java:6)
...
在主線程發(fā)生除以0的算術(shù)異常次洼。而且在div方法下的語句沒有執(zhí)行,說明程序只是執(zhí)行到了發(fā)生異常的語句遇骑。
接下來我們來處理異常卖毁。將代碼按照下方代碼修改。
public class Main {
public static void main(String[] args) {
try {
div(4,0);
System.out.println("執(zhí)行可能存在問題的代碼");
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
System.out.println("捕獲異常");
}
}
public static int div(int a, int b) throws
ArithmeticException{
if(b == 0) {
throw new ArithmeticException("除數(shù)不能為0");
}
return a / b;
}
}
我們在方法 div 后面聲明可能拋出算術(shù)異常:throws ArithmeticException落萎。然后產(chǎn)生錯誤的語句放入try-catch語句的try中亥啦,在catch將捕獲的異常及其追蹤輸出至標(biāo)準(zhǔn)錯誤流:e.printStackTrace()。再將通過 getMessage() 方法獲取的錯誤信息打印出來练链。為了讓用戶更好的了解異常翔脱,我們自己創(chuàng)建異常對象,并寫上異常信息媒鼓,然后拋出届吁。語句: throw new ArithmeticException("除數(shù)不能為0");
結(jié)果如下:
除數(shù)不能為0
java.lang.ArithmeticException: 除數(shù)不能為0
捕獲異常
at com.xxx.Main.div(Main.java:18)
at com.xxx.Main.main(Main.java:7)
我們發(fā)現(xiàn)異常信息使我們自定義的了错妖。
例2:
有時候我們需要自定義一些異常,參照下面的代碼就可以自己自定義一場了疚沐。這里try-catch語句變?yōu)榱藅ry-catch-finally語句暂氯。finally語句是無論是否發(fā)生異常,都將執(zhí)行的語句塊亮蛔。
public class Main {
public static void main(String[] args) {
Computer computer = new Computer();
// 多個異常捕獲痴施,異常對象存在父子關(guān)系時,要求父類異常必須寫在下面
// try {
// computer.setStatus("進水");
// } catch (EnterWaterException e) {
// e.printStackTrace();
// } catch (Exception e) {
// e.printStackTrace();
// }
// 多個異扯耍可以合并在一個catch塊
try {
computer.setStatus("進水了");
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("finally");
}
}
}
class Computer {
private String status;
public String getStatus() {
return status;
}
public void setStatus(String status) throws DownException, EnterWaterException {
this.status = status;
if (status.equals("進水了")) {
throw new EnterWaterException("進水了晾剖,短路了");
} else if (status.equals("摔了")) {
throw new DownException("摔了,碎了");
}
}
}
class EnterWaterException extends RuntimeException{
public EnterWaterException(String message) {
super(message);
}
}
class DownException extends RuntimeException{
public DownException(String message) {
super(message);
}
}
使用異常需要注意的問題
1.runtime的異程菟裕可以不捕獲就可以過編譯。
2.多個異常捕獲沽损,異常對象存在父子關(guān)系時灯节,要求父類異常必須寫在下面。
3.多個異常如果沒有不一樣的操作可以合并在一個catch塊中绵估,參數(shù)用共同的父類炎疆。
更多的注意事項請參考Java中的異常處理中的“那些不好的習(xí)慣”。
常見異常
在Java中提供了一些異常用來描述經(jīng)常發(fā)生的錯誤国裳,對于這些異常形入,有的需要程序員進行捕獲處理或聲明拋出,有的是由Java虛擬機自動進行捕獲處理缝左。
RuntimeException子類:
1亿遂、 java.lang.ArrayIndexOutOfBoundsException 數(shù)組索引越界異常。當(dāng)對數(shù)組的索引值為負(fù)數(shù)或大于等于數(shù)組大小時拋出渺杉。
2蛇数、java.lang.ArithmeticException 算術(shù)條件異常。譬如:整數(shù)除零等是越。
3耳舅、java.lang.NullPointerException 空指針異常。當(dāng)應(yīng)用試圖在要求使用對象的地方使用了null時倚评,拋出該異常浦徊。譬如:調(diào)用null對象的實例方法、訪問null對象的屬性天梧、計算null對象的長度盔性、使用throw語句拋出null等等。
4腿倚、java.lang.ClassNotFoundException 找不到類異常纯出。當(dāng)應(yīng)用試圖根據(jù)字符串形式的類名構(gòu)造類蚯妇,而在遍歷CLASSPAH之后找不到對應(yīng)名稱的class文件時,拋出該異常暂筝。
5箩言、java.lang.NegativeArraySizeException 數(shù)組長度為負(fù)異常
6、java.lang.ArrayStoreException 數(shù)組中包含不兼容的值拋出的異常
7焕襟、java.lang.SecurityException 安全性異常
8陨收、java.lang.IllegalArgumentException 非法參數(shù)異常
IOException
1、IOException:操作輸入流和輸出流時可能出現(xiàn)的異常鸵赖。
2务漩、EOFException 文件已結(jié)束異常
3、FileNotFoundException 文件未找到異常
其他
1它褪、ClassCastException 類型轉(zhuǎn)換異常類
2饵骨、ArrayStoreException 數(shù)組中包含不兼容的值拋出的異常
3、SQLException 操作數(shù)據(jù)庫異常類
4茫打、NoSuchFieldException 字段未找到異常
5居触、NoSuchMethodException 方法未找到拋出的異常
6、NumberFormatException 字符串轉(zhuǎn)換為數(shù)字拋出的異常
7老赤、StringIndexOutOfBoundsException 字符串索引超出范圍拋出的異常
8轮洋、IllegalAccessException 不允許訪問某類異常
9、InstantiationException 當(dāng)應(yīng)用程序試圖使用Class類中的newInstance()方法創(chuàng)建一個類的實例抬旺,而指定的類對象無法被實例化時弊予,拋出該異常
參考博客:
http://blog.csdn.net/hguisu/article/details/6155636
http://www.jellythink.com/archives/1420