Java異常
一、概念
1琳拭、異常:有異于常態(tài)训堆,和正常情況不一樣,有錯(cuò)誤出現(xiàn)白嘁,阻止當(dāng)前方法或作用域坑鱼。
2、異常處理:將出現(xiàn)的異常提示給編程人員與用戶絮缅,使原本將要中斷的程序繼續(xù)運(yùn)行或者退出鲁沥。并且能夠保存數(shù)據(jù)和釋放資源。
二耕魄、異常體系結(jié)構(gòu)
1画恰、所有異常都繼承于Throwable類,其下有兩大子類:
- (1)Error類:錯(cuò)誤吸奴,一般編程人員不太接觸允扇,如虛擬機(jī)錯(cuò)誤、線程死鎖则奥。硬傷:使程序崩潰
- (2)Exception類:異常考润,編碼、環(huán)境读处、用戶輸入等問題糊治,其子類主要有:
-
非檢查異常(運(yùn)行時(shí)異常RuntimeException):【由java虛擬機(jī)自動(dòng)捕獲】如空指針NullPointer、越界ArrayIndexOutofBounds档泽、錯(cuò)誤類型轉(zhuǎn)換ClassCast俊戳、算數(shù)異常Arithmetic等
-
- 檢查異常CheckException:【需要手動(dòng)添加捕獲和處理語句】文件異常IO等
三揖赴、異常處理:
try-catch(多catch塊)-finally
- (1)try塊:負(fù)責(zé)捕獲異常馆匿,一旦try中發(fā)現(xiàn)異常,程序的控制權(quán)將被移交給catch塊中的異常處理程序燥滑〗ケ保【try語句塊不可以獨(dú)立存在,必須與 catch 或者 finally 塊同存】
- (2)catch塊:如何處理铭拧?比如發(fā)出警告:提示赃蛛、檢查配置、網(wǎng)絡(luò)連接搀菩,記錄錯(cuò)誤等呕臂。執(zhí)行完catch塊之后程序跳出catch塊,繼續(xù)執(zhí)行后面的代碼肪跋。
-
編寫catch塊的注意事項(xiàng):多個(gè)catch塊處理的異常類歧蒋,要按照先catch子類后catch父類的處理方式,因?yàn)闀?huì)【就近處理】異常(由上自下)。
-
編寫catch塊的注意事項(xiàng):多個(gè)catch塊處理的異常類歧蒋,要按照先catch子類后catch父類的處理方式,因?yàn)闀?huì)【就近處理】異常(由上自下)。
- (3)finally:最終執(zhí)行的代碼谜洽,用于關(guān)閉和釋放資源等
try{
//一些會(huì)拋出的異常
}catch(Exception e){
//處理該異常的代碼塊
}finally{
//最終要執(zhí)行的代碼
}
try-catch-finally執(zhí)行順序:
- ①執(zhí)行try{}塊
- ②如果try{}塊有異常產(chǎn)生萝映,執(zhí)行catch{}塊
- ③無論有沒有異常都要執(zhí)行finally{}塊,這里可以看出只要finally中有return阐虚,必然返回finally{}中的return
return的執(zhí)行序臂,
- ①,如果finally{}塊中有return語句实束,只執(zhí)行finally{}塊中的return語句
- ②奥秆,如果finally{}塊中沒有return語句,如果try{}有異常咸灿,則返回catch{}中的return語句吭练,不然執(zhí)行try{}中return語句
如果finally語句塊中有return語句,try/catch語句塊中的return語句會(huì)被忽視
在try-catch-finally之外還可以有return析显,這種情況下在catch和try里面兩者之一能有return鲫咽,不能同時(shí)有,且當(dāng)當(dāng)有兩者之一語句執(zhí)行時(shí)會(huì)返回兩者之一的return谷异,不會(huì)返回語句外的return值分尸,當(dāng)兩者之一的return不執(zhí)行時(shí)才會(huì)返回語句外的return值。finally與語句外不能同時(shí)存在return歹嘹,當(dāng)否則會(huì)報(bào)錯(cuò)
四箩绍、Java 中的異常拋出以及自定義異常
兩個(gè)重要的關(guān)鍵字:throw和throws
- 1.throws的異常列表可以是拋出一條異常,也可以是拋出多條異常尺上,每個(gè)類型的異常中間用逗號隔開
- 2.方法體中調(diào)用會(huì)拋出異常的方法或者是先拋出一個(gè)異常:用throw new Exception()
throw寫在方法體里材蛛,表示“拋出異常”這個(gè)動(dòng)作 - 3.如果某個(gè)方法調(diào)用了拋出異常的方法怎抛,那么必須添加try catch語句去嘗試捕獲這種異常卑吭,
或者添加聲明,將異常拋出給更上一層的調(diào)用者進(jìn)行處理 - 4.自定義異常:
class 自定義異常類 extends 異常類型{
}
上面的異常類型可以是Exception马绝,也可以是其子類
Java 中的異常鏈
只有Error豆赏,Exception,RuntimeException提供了帶cause參數(shù)的構(gòu)造器富稻,其他的所有異常類只能通過initCause()來設(shè)置cause掷邦。
所有Throwable的子類構(gòu)造器中都可以接受一個(gè)cause對象作為參數(shù)。cause是異常原由椭赋,代表著原始異常抚岗。既可以在當(dāng)前位置創(chuàng)建并拋出行的異常,也可以通過cause追蹤到異常最初發(fā)生的位置哪怔。
異常鏈?zhǔn)且环N面向?qū)ο缶幊碳夹g(shù)宣蔚,指將捕獲的異常包裝進(jìn)一個(gè)新的異常中并重新拋出的異常處理方式廷痘。原異常被保存為新異常的一個(gè)屬性(比如cause)。這個(gè)想法是指一個(gè)方法應(yīng)該拋出定義在相同的抽象層次上的異常件已,但不會(huì)丟棄更低層次的信息笋额。
把捕獲的異常包裝成新的異常,在新異常里添加原始的異常篷扩,并將新異常拋出兄猩,它們就像是鏈?zhǔn)椒磻?yīng)一樣,一個(gè)導(dǎo)致(cause)另一個(gè)
這個(gè)想法是指一個(gè)方法應(yīng)該拋出定義在相同的抽象層次上的異常鉴未,(將所有捕獲到的異常包裝為新的異常類枢冤,即定義在相同的抽象層次上拋出)但不會(huì)丟棄更低層次的信息。
實(shí)現(xiàn)異常鏈功能的兩種基本寫法:
public class ChainTest {
/**
* test1()拋出喝大了異常
* test2()調(diào)用test1()捕獲喝大了異常铜秆,并且包裝成運(yùn)行時(shí)異常淹真,繼續(xù)拋出
* main方法中調(diào)用test2(),嘗試捕獲 test2()方法拋出的異常
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ChainTest ct = new ChainTest();
try{
ct.test2();
}catch(Exception e){
e.printStackTrace();
}
}
public void test1() throws DrunkException{
throw new DrunkException("喝酒別開車");
}
public void test2(){
try {
test1();
} catch (DrunkException e) {
// TODO Auto-generated catch block
RuntimeException newExc = new RuntimeException("司機(jī)一滴酒连茧,親人兩行淚");
newExc.initCause(e);
throw newExc;
}
}
}