我覺得
Java
的異常處理要精簡
,
因?yàn)?/span>
,
處理異常需要
JVM
付出額外的開銷
.Java
異常的根類為
java.lang.Throwable,
其有兩個(gè)直接的子類
:java.lang.Error
和
java.lang.Exception. Error
表示程序本身無法恢復(fù)的嚴(yán)重錯(cuò)誤
;Exception
類表示可以被程序捕獲并處理的
Bug.
我們也可以自定義類來拋出異常
,
但是都必須直接或間接繼承
Exception
類
.
(一)
錯(cuò)誤處理與
JVM
用方法調(diào)用堆棧
我們知道
,JVM
用方法調(diào)用棧
(Stack)
來跟蹤每個(gè)線程中一系列的方法調(diào)用過程
.
該棧保存了每個(gè)調(diào)用方法的本地信息
.
如
:
一個(gè)棧中已經(jīng)有三個(gè)方法
,MethodB
為當(dāng)前正在執(zhí)行的方法
如果這個(gè)時(shí)候
,
方法中的代碼可能拋出異常
,
將會有兩種處理
方法
:
? 1).
? Public void methodB(int a) {
??? Try{
??????
? //do
????? If(a<0) throw new SpecialException();
??? }catch(SpecialException e){
????? //do with Exception
?? }
? }
? 2).
在方法的聲明處通過
throws
語句聲明拋出異常
,
如
:
?? Public void mothodB(int a) throws SpecialException{
???? //do
???? If(a<0) throw new SpecialException();
?? }
當(dāng)
java
的方法正常執(zhí)行完畢
,JVM
會從
Stack
中彈出該方法的棧結(jié)構(gòu)
,
然后繼續(xù)處理前一個(gè)方法
.
如果
java
方法在執(zhí)行代碼過程中拋出異常
,JVM
必須找到能捕獲該異常的
Catch
代碼塊
.
他首先查看當(dāng)前方法是否存在這樣的
Catch
代碼塊
,
如果存在
,
就執(zhí)行
catch
代碼
,
否則
,JVM
會從調(diào)用棧中彈出該方法的棧結(jié)構(gòu)
,
繼續(xù)到前一個(gè)方法中查找合適的
catch
代碼塊
.
?
例如
:
當(dāng)
MethodB()
方法拋出
SpecialException
時(shí)
,
如果在該方法中提供了捕獲
SpecialException
的
Catch
代碼塊
,
就執(zhí)行這個(gè)異常處理代碼塊
,
否則
,
如果采用第二種方式聲明繼續(xù)拋出
SpecialException,JVM
的處理流程將退回到上層調(diào)用方法
MethodA(),
再查看
A
有沒有捕獲
SpecialException.
如果
,A
方法中存在捕獲
SpecialException
的
catch
代碼塊
,
就執(zhí)行
.
此時(shí)
A
方法定義如下
:
? Public void methodA(int a){
??? Try{
??????? methodB(a);
?????? }catch(SpecialException e){
???
?????//do with Exception
?????? }}
如果
,A
方法也沒有捕獲
SpecialException,
而只是聲明拋出
SpecialException,JVM
處理流程將繼續(xù)退回到
main()
方法
.
如果
,main()
里面仍然沒有找到處理該異常的代碼
,
該線程就會異常終止
.
如果
,
該線程是主線程
,
應(yīng)用程序也會終止
.
用戶終端就會看到原始異常信息
.
?
一般說來,在
java
程序中使用
try/catch
不會對應(yīng)用程序有很大的影響,僅僅當(dāng)異常發(fā)生時(shí),
JVM
虛擬執(zhí)行額外的操作,來定位處理異常的代碼塊,這時(shí),對系統(tǒng)性能產(chǎn)生負(fù)面影響。但是,如果拋出異常的代碼和捕獲異常的代碼在一個(gè)方法中,這種影響就會小些,因此,不應(yīng)該用異常處理機(jī)制來控制程序的正常流程,而應(yīng)該僅僅用在程序可能出現(xiàn)異常的地方才使用
try/catch
。