異常的丟擲和捕捉
這節課來學習異常的丟擲和捕捉。
首先,什麼叫丟擲異常?程式碼解釋。
算了,常用異常類以後看到了再講。
接下來所有編譯時異常類我們就直接拋Exception,執行時異常拋RuntimeException
Demo1:
//我們選擇繼續丟擲 public static void main(String[] args) throws Exception { Scanner scanner = new Scanner(System.in); int a = scanner.nextInt(); exceptionThrowTest(a); //因為exceptionThrowTest方法是選擇向外層拋異常,所以異常會被丟擲到這一層,這個時候我們還是要選擇捕獲或者繼續丟擲 } //先來寫個方法吧 //向外丟擲異常,這是一個宣告,表明這個方法裡丟擲的異常最後會向外層拋 //什麼叫外層呢?呼叫這個方法的那一層就叫這個方法的外層 public static void exceptionThrowTest(int a) throws Exception { if (a<0) { //丟擲異常 throw new Exception("傳入的引數不可以為負數");//這裡報紅,說明編譯時異常必須被顯示丟擲或捕獲 } }
輸入:
-2
輸出:
Exception in thread "main" java.lang.Exception: 傳入的引數不可以為負數
上節課說過,如果最外層沒有捕獲異常,程式會直接停止執行並列印異常資訊
異常資訊的結構就是:
異常名+在哪裡出異常+異常全類名: 異常裡的detailMessage屬性
原始碼摘取:
public Exception(String message) {
super(message);
}
public Throwable(String message) {
fillInStackTrace();
detailMessage = message;
}
可以看到輸出的就是我們傳給Exception構造器的那個字串引數
接下來看執行時異常
Demo2:
public static void main(String[] args){ Scanner scanner = new Scanner(System.in); int a = scanner.nextInt(); runtimeExceptionThrowTest(a); }
public static void runtimeExceptionThrowTest(int a)
{
if (a<0)
{
//丟擲異常
throw new RuntimeException("傳入的引數不可以為負數");//這裡報紅,說明編譯時異常必須被顯示丟擲或捕獲
}
}
輸入:
-2
輸出:
Exception in thread "main" java.lang.RuntimeException: 傳入的引數不可以為負數
結論:執行時異常的丟擲可以不必被顯示捕獲或丟擲,如果不被顯示捕獲和丟擲,預設向外層丟擲
接下來看異常的捕獲:
異常的捕獲需要用到try-catch語法結構,還是直接看程式碼:
被try/catch包裹
try-catch語法:
try{
可能會丟擲異常的程式碼片段
}catch(異常類 變數名){
處理程式碼
}
Demo 3:
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
//我們來手寫一下
try{
//可能會丟擲異常的片段
exceptionThrowTest(a);
}catch(Exception e){
System.out.println("出異常啦");
}
System.out.println("異常已經被捕獲並且處理啦,程式還是會繼續執行,不會終止的哦");
}
輸入:
-3
輸出:
出異常啦
異常已經被捕獲並且處理啦,程式還是會繼續執行,不會終止的哦
結論:
- 如果丟擲的異常被捕獲了,程式會繼續執行,而不會終止執行。
- try塊裡的程式碼如果丟擲異常,則try塊裡的程式碼不會繼續執行,而是轉到catch塊裡執行。
- 一個try可以對應多個catch,catch的規則應該是先catch子類異常,後catch父類異常,且一個異常只會被catch一次
- 所有異常都繼承自Exception,所以在最後catch一下Exception是一個好習慣
- 執行時異常也可以被catch哦
Demo 4:
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
//我們來手寫一下
try{
runtimeExceptionThrowTest(a);
exceptionThrowTest(a);
}catch (RuntimeException e){
System.out.println("這裡被RuntimeException捕獲啦");
e.printStackTrace(); //輸出異常資訊
} catch(Exception e){
System.out.println("出異常啦");
e.printStackTrace(); //輸出異常資訊
}
//runtimeExceptionThrowTest(a);
System.out.println("異常已經被捕獲並且處理啦,程式還是會繼續執行,不會終止的哦");
}
public static void exceptionThrowTest(int a) throws Exception
{
if (a>0)
{
//丟擲異常
throw new Exception("傳入的引數不可以為正數");//這裡報紅,說明編譯時異常必須被顯示丟擲或捕獲
}
}
public static void runtimeExceptionThrowTest(int a)
{
if (a<0)
{
//丟擲異常
throw new RuntimeException("傳入的引數不可以為負數");//這裡報紅,說明編譯時異常必須被顯示丟擲或捕獲
}
}
輸入:
2
輸出:
出異常啦
java.lang.Exception: 傳入的引數不可以為正數
at helloworld.exception.ExceptionTeach.exceptionThrowTest(ExceptionTeach.java:34)
at helloworld.exception.ExceptionTeach.main(ExceptionTeach.java:14)
異常已經被捕獲並且處理啦,程式還是會繼續執行,不會終止的哦
輸出順序應該是上面這樣的,idea輸出的順序不太符合我們預想的結果哈,不過內容輸出的沒錯,只是順序問題而已,這個應該是idea的問題
分析:
輸入2,丟擲的是Exception異常,所以不會捕獲RuntimeException異常,也就不會輸出”這裡被RuntimeException捕獲啦”
輸入:
-1
輸出:
這裡被RuntimeException捕獲啦
java.lang.RuntimeException: 傳入的引數不可以為負數
at helloworld.exception.ExceptionTeach.runtimeExceptionThrowTest(ExceptionTeach.java:43)
at helloworld.exception.ExceptionTeach.main(ExceptionTeach.java:13)
異常已經被捕獲並且處理啦,程式還是會繼續執行,不會終止的哦
分析:
這個顯然捕獲的是RuntimeException啦,而且根據輸出資訊可以看出異常只會被捕獲一次,因為處理Exception異常的程式碼並沒有被執行
注意:
差點忘記說了,這裡的是throws,表明可以丟擲多個異常,多個異常用逗號隔開
throws丟擲的異常不一定會被丟擲,throws只是負責向外拋這個方法捕獲到的異常,不負責判斷這個異常到底有沒有被捕獲到,所以throws後面可以隨便寫
但是,throws後面必須包含本方法可能被丟擲的異常,除非這個異常在本方法內已經被捕獲了或者這個異常是執行時異常
這個就是異常的丟擲和捕獲。