java異常-父類異常與子類異常之間的捕獲關係
阿新 • • 發佈:2018-12-24
class Annoyance extends Exception {} class Sneeze extends Annoyance {} class Human { public static void main(String[] args) throws Exception { try { try { throw new Sneeze(); } catch ( Annoyance a ) { System.out.println("Caught Annoyance"); throw a; } } catch ( Sneeze s ) { System.out.println("Caught Sneeze"); return ; } finally { System.out.println("Hello World!"); } } }
今天看到這麼一段程式碼,請問輸出的內容是什麼?
先別給出答案,思考一下平時我們寫程式碼的過程中,異常捕獲的過程和順序,比如有這麼一段程式碼:
try {
throw new FileNotFoundException();
} catch (IOException e) {
}
我們經常能看到這樣的程式碼,也就是使用父類能夠捕獲子類的異常,當然所有的異常都是繼承Exception的,那麼為什麼不用Exception替換所有具體的異常類呢?這個是要考慮到我們對程式碼中預期異常的掌握,也就是某些程式碼會產生什麼樣的異常,程式設計師應當心中有數,如果全都用Exception的引用來接收,大家都是稀裡糊塗的,如何進行處理也會變得難以著手。但如果在Catch程式碼塊中不打算做任何處理,僅捕獲而已,那麼這時使用Exception也沒什麼關係,但正是生產環境下,這樣的情況應該不允許存在的,這個看JDK的原始碼就知道了,捕獲異常以後一定要給出提示資訊的。以上的程式碼證明了,我們可以用父類的引用接受子類的異常物件,那麼問題來了,最上面的程式碼執行結果是什麼呢?答案是:
Caught Annoyance
Caught Sneeze
Hello World!
相信第一行和第三行大家都沒什麼疑問了,關鍵是第二行,應該出來嗎?是不是子類捕獲了父類的異常呢?
經過斷點的加入,我們發現,儘管
catch ( Annoyance a )
這一句使用的是父類的引用,但實際上是子類的物件,這是java中多型的經典表現。在catch ( Sneeze s )
的時候當然可以捕獲到自己丟擲來的異常了。
為了證明,子類從本質上無法捕獲父類的異常,我們繼續做個試驗:
try {
throw new Annoyance();
} catch (Sneeze s) {
System.out.println("Caught Sneeze");
return;
} finally {
System.out.println("Hello World!");
}
可以看到,丟擲了父類的異常,使用子類catch,這時候可以通過編譯,但執行時呢?Hello World!
Exception in thread "main" com.xq.exceptions.Annoyance
at com.xq.exceptions.Human.main(ExceptionTest.java:14)
可以看到,出了問題了,也就是說,父類throw出來的異常,子類並沒有捕獲到,繼續往下證明:
try {
throw new Annoyance();
} catch (Sneeze s) {
System.out.println("Caught Sneeze");
return;
} catch (Exception e) {
System.out.println("Caught Exception");
return;
} finally {
System.out.println("Hello World!");
}
既然子類捕獲不了,那就使用Exception,可以看到結果如下:
Caught Exception
Hello World!
看到這樣,大家肯定都明白了,不用多說了!