Java中允許對異常進行再次抛出,以送出給上一層進行處理,最為明顯的例子為Java的正常異常。
正常異常:有Java所定義的異常,不需要異常聲明,在未被try-catch的情況下,會被預設上報到main()方法。
Example:
public class TestException {
TestException(int i) throws ExceptionA,ExceptionB{
int a[]={0,}; a[1]=1;
}
}
當從main()方法中調用TestException類的構造函數的時候,會得到以下的異常提示,從中可以看出異常的冒泡機制(這是一個棧資訊)。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5CNkNDOjRWMzE2MwMWMmJ2M5gzNzIzNyY2N1YTYwQTOl9CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
異常的冒泡上傳機制:當一個異常對象産生了以後,其會按照調用層次(一般是方法的調用層次)進行冒泡,直到被try-catch處理,或上報至main()方法,有編譯器進行提示。
Example:
firstThrow()提示錯誤的原因為, firstThrow()的函數聲明中包括了MyException的異常聲明,而secondThrow()中調用了firstThrow()卻未對可能抛出的異常對象提供任何處理方案,這是編譯器所不能允許發生的事情。(這也是為了保證底層異常對象在冒泡過程中,能得到合适的處理和重視!)
注意此截圖中,MyEclipse提供了兩種方式幫助fix這個程式,這兩種方式常用的異常應對手段:
1、本方法不給予處理,将異常上報給上一層。
1 public classTestExceptionChain {2 void firstThrow() throwsMyException3 {4 print("Oringinally creat a MyException and throw it out");5 throw newMyException();6
7 }8 void secondThrow() throwsMyException9 {10 firstThrow();11 }12 TestExceptionChain() throwsMyException{13 secondThrow();14 }15 }
1 public static voidmain(String[] args) {2 try{3
4 TestExceptionChain testExceptionChain=newTestExceptionChain();5 }6 catch(MyException e)7 {8 e.printStackTrace();9 print("Catch a my exception!");10 }11
12 }
控制台的輸出為:
從異常棧的記錄資訊可以發現,與代碼相對應的異常抛出機制和次序:
firstThrow()産生MyException對象->異常冒泡至調用其的secondThrow()->異常冒泡至調用secondThrow()的TestExceptionChain的構造方法->冒泡至printtry的main()方法。
注意到:異常對象一直被抛出,直至在printtry的mian()方法中被try-catch捕獲!
2、try-catch方式,捕捉上報的異常,而後進行相應處理或抛出另一異常。
2、1捕獲異常後,進行相應處理。
Example:
1 public classTestExceptionChain {2 void firstThrow() throwsMyException3 {4 print("Oringinally creat a MyException and throw it out");5 throw newMyException();6 }7 voidsecondThrow()8 {9 try
10 {11 firstThrow();12 }13 catch(MyException e)14 {15 print("I have just caught a MyExcepton,but i want to do nothing for it");16 e.printStackTrace();17 }18 }19 TestExceptionChain(){20 secondThrow();21 }
從圖中可以發現,異常在secondThrow() 中被try-catch子產品捕獲,并執行了相應的處理操作,是以其函數聲明中無需添加異常聲明,異常不會被上報。
故mian()方法被改寫成了以下的代碼:
1 TestExceptionChain testExceptionChain=new TestExceptionChain();
注意此處異常棧的資訊,表示的是異常産生的層次資訊,并非異常資訊的上報層次,因為其已經在secondThorow()中被捕獲處理。
2.2 捕獲異常後,抛出另一個異常。
Example:
1 public classTestExceptionChain {2 void firstThrow() throwsMyException3 {4 print("Oringinally creat a MyException and throw it out");5 throw newMyException();6 }7 void secondThrow() throwsYouException8 {9 try
10 {11 firstThrow();12 }13 catch(MyException e)14 {15 print("I have just caught a MyExcepton,but i want to create a YouException and throw it out");16 e.printStackTrace();17 throw newYouException();18 }19 }20 TestExceptionChain() throwsYouException{21 secondThrow();22 }23 }24 class MyException extendsException{}25 class YouException extends Exception{}
從異常棧資訊中可以發現,新抛出的YouException對象是從secondThrow()中開始的。
*Java中還提供了fillInStackTrace()方法,用于對捕獲的異常的棧資訊進行重寫。
Example:
1 try{2
3 TestExceptionChain testExceptionChain=newTestExceptionChain();4 }5 catch(YouException e)6 {7 print("Catch a YouException!");8 e.fillInStackTrace();9 e.printStackTrace();10
11 }
由于使用了fillInstack()方法,關于YouException的異常資訊被重寫,從其被從寫處重新記錄!