異常處理機制-Exception
異常類在java.lang包中。
拋出異常應(yīng)該使用的關(guān)鍵字是throw.
1.異常的基本介紹
(1).定義
異常處理是java中重要的容錯方式。為什么要進(jìn)行異常處理呢?
容錯:在程序設(shè)計時,要考慮周密,針對可能發(fā)生的意外進(jìn)行預(yù)防措施,在程序上加上相應(yīng)的處理指令。
異常:Java中處理錯誤的一種機制。
拋出異常:Java程序在執(zhí)行過程中如果出現(xiàn)異常事件,可以生產(chǎn)一個異常對象,這個異常對象封裝了異常信息,并被提交給運行時系統(tǒng)。
捕獲異常:當(dāng)運行時系統(tǒng)接收到異常對象時,會把當(dāng)前的異常對象交由能處理這一異常的代碼進(jìn)行處理。(catch進(jìn)行捕獲異常。)
try{
//此處是拋出異常部分,但這個異常對象的拋出不是由程序的語句完成的,是JVM(虛擬機)完成的。
}catch(Exception e){
}
(2).異常的分類
Throwable類是Java語言中所有錯誤或異常的父類。Exception是所有異常的父類。

2.異常處理規(guī)則
異常捕獲和處理是用try-catch-finally語句結(jié)構(gòu)完成的。
(1)語句格式
try{
語句組1
}catch(異常類 1 對象名){
語句組2
}catch(異常類2 對象名){
語句組3
}
.......
}finally{
語句組4
}
解釋:(1)try代碼部分叫做try 語句塊,(拋出異常部分),包含可能產(chǎn)生異常的代碼,一個try語句塊可以拋出一個或多個異常,catch進(jìn)行捕獲和處理。try不能脫離catch代碼塊或finally代碼塊而單獨存在。try代碼塊后面至少有一個catch代碼塊或者finally代碼塊,但finally代碼塊只能是0個或1個。try代碼塊后面可以是try{ ?}catch{ },也可以是try{ ? }finally{ ?}.如果try代碼塊沒有拋出異常,就會跳過catch語句塊。
? ?try 中某行代碼拋出異常后,將終止下面的程序執(zhí)行,轉(zhuǎn)去對應(yīng)的catch代碼塊進(jìn)行處理異常(一次匹配成功則進(jìn)行處理,,處理后的catch的其他類型語句就不再執(zhí)行了,但是finally和其他語句要執(zhí)行;如果一次不行,則一直匹配到成功;若所有的catch都沒有匹配,則視為異常未處理,finally的語句可以執(zhí)行,但finally代碼塊后面的程序不執(zhí)行。)catch在這里就是個選擇語句,選擇相對應(yīng)的異常類型進(jìn)行執(zhí)行
? ? ? ? ?(2)catch 代碼塊進(jìn)行異常的捕獲和處理,每個try代碼塊后面可以跟一個或多個catch代碼塊,用來處理不同類型的異常對象,即格式為catch(異常類型 ?異常參數(shù)(相當(dāng)于方法中的形參))。
? ? catch代碼塊的異常對象封裝了異常事件發(fā)生的信息,在catch語句塊中可以使用異常對象的方法獲取被封裝的異常事件的發(fā)生:
getMessage():返回異常信息
printStackTrace():用來跟蹤異常事件發(fā)生時執(zhí)行堆棧的內(nèi)容。經(jīng)常出現(xiàn)的語句是
catch(Exception e){
e.printStackTrace();
}
寫catch(異常類型 異常參數(shù))時,必須子類異常在前,父類異常在后。catch 異常類型的排列順序是從子類到父類排列,反之有錯,且無意義。
? ? ? ? (3)finally語句塊就是為異常處理提供了一個出口,在finally代碼塊中進(jìn)行資源清除工作,如關(guān)閉打開的文件,清除臨時文件。無論try語句是否拋出異常,finally代碼塊都要執(zhí)行。
注:finally代碼塊不執(zhí)行的情況:先執(zhí)行了System.exit();
如果catch語句塊和finally語句塊并存,則catch代碼塊必須在finally代碼塊的前面。
? ? ? ?(4)throw e /throws?
(2)方法調(diào)用時的異常處理
一個方法拋出異常,由上一級調(diào)用的此方法拋出,如無法處理,一直向上一級拋出,最后拋給main方法。如處理繼續(xù)執(zhí)行,否則就會程序中斷。


異常前有return怎么處理,怎么運行的?
3.異常類的定義與使用
在寫程序時,除了使用Java類庫中的異常類外,有時需要在程序中根據(jù)具體情況定義一些異常類。
自己定義的異常類通常是Exception的子類,或是Throwable的子類或間接子類。
(1)定義異常類
class numException extends Exception{
//定義成員變量reason
private String reason;
//記錄異常原因
public numException(String r)
rason = r;?
}
//定義成員方法,getReason()返回異常原因
public String getReason(){
? ?return (reason);
}
(2)創(chuàng)建并拋出異常對象
創(chuàng)建、拋出異常對象時在方法體中完成的,格式如下:
修飾符 返回類型 方法名(參數(shù)列表) throws 異常類名表?
{
...
throw 異常對象;//出現(xiàn)在方法中,說明這個方法可能會拋出異常對象,那么在調(diào)用這個方法時要進(jìn)行相應(yīng)的異常捕獲和處理。
}
當(dāng)方法頭部出現(xiàn)了“throws ?異常類名表 ”,則必須進(jìn)行相應(yīng)的異常捕獲處理,否則會出錯。
實例:
NumExceptionText.java
package Exception;
//異常處理:學(xué)號位數(shù)不對,應(yīng)該是九位
/*(1)首先自定義自己的異常,該異常繼承Exception
* 為自己定義的異常設(shè)置成員變量,設(shè)置構(gòu)造器,設(shè)置getReason()方法
*(2)設(shè)置非主類Student,在方法(void setStudent())中進(jìn)行引用自定義的類拋出( throws numException),
*在方法體中設(shè)置,以及設(shè)置 throw new numException("拋出異常信息提示"
*(3)在主類中進(jìn)行實例化,還有進(jìn)行try(調(diào)用在非主類中設(shè)置的st.setStudent("傳值")的方法傳入值)-catch異常處理。
*/
class numException extends Exception{
? ? private String reason;
public numException(String r) {
super();
this.reason = r;
}
public String getReason() {
return reason;
}? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
}
class Student{
private String studentNo,name;
void setStudent(String stuNo, String nm) throws numException {
if(stuNo.length()!=9)
throw new numException("學(xué)號位數(shù)不對,應(yīng)該是9位!");
this.studentNo = stuNo;
this.name = nm;
}
void showInfo(){
System.out.println("學(xué)號:"+this.studentNo);
System.out.println("姓名:"+this.name);
}
}
public class NumExceptionTest {
public static void main(String[] args) {
Student st = new Student();
try{
st.setStudent("12345678","張三"); //錯誤的信息,會拋出異常
//st.setStudent("123456789", "張三"); // 正確的信息會輸出學(xué)號和姓名
}catch(numException e){
System.out.println(e.getReason());
}
st.showInfo();
}
}
郵政編碼的異常處理
customerTest.java
package Exception;
class AddressException extends Exception{
private String reason;
public AddressException(String r) {
super();
this.reason = r;
}
public String getReason() {
return reason;
}
}
class Customer{
private String name;
private String? Address;
private String emailnumAddess;
void setCustomer(String nm,String ad,String enumd) throws AddressException{
if(enumd.length()!= 6)
throw new AddressException("郵政編碼必須是6位數(shù)字!");
this.name = nm;
this.Address = ad;
this.emailnumAddess = enumd;
}
void showInfo(){
System.out.println("姓名:"+this.name);
System.out.println("地址:"+this.Address);
System.out.println("郵政編碼:"+this.emailnumAddess);
}
}
public class customerTest {
public static void main(String[] args) {
Customer c = new Customer();
try{
c.setCustomer("李四", "海棠路", "123456");
}catch(AddressException e){
System.out.println(e.getReason());
}
c.showInfo();
}
}