1. 程式人生 > >java異常-父類異常與子類異常之間的捕獲關係

java異常-父類異常與子類異常之間的捕獲關係

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!

看到這樣,大家肯定都明白了,不用多說了!