[Java基礎篇]Java異常模塊

前言

Java的基本理念是結構不佳的代碼將不能運行。
異常(不期而至的各種狀況)是程序中地一些錯誤,並不是所有的錯誤都是異常,但是有時候錯誤可以避免的。異常是一個事件,它發生在程序運行期間,干擾了正常的指令流程。

一、Java中的異常層次結構

在這裏插入圖片描述
Error類(專門用來處理嚴重影響程序運行的錯誤,無法處理的錯誤,好比絕症): Java運行時系統的內部錯誤資源耗盡錯誤。應用程序不應該拋出這種類型的對象。如果出現了這樣的內部錯誤,除了通告給用戶,並盡力使程序安全地終止之外,再也無能爲力。
Exception(好比感冒、闌尾炎): 表示異常,異常產生後程序員可以通過代碼的方式糾正,使程序繼續運行,必須要處理的。這種異常分爲兩大類:運行時異常和非運行時異常。
RuntimeException(運行異常): 由程序邏輯錯誤導致的異常。Java編譯器不會檢查它的,編譯會通過。
非運行時異常(編譯錯誤):RuntimeException以外的異常,類型上都屬於Exception類及其子類。從程序語法上說是必須進行處理的異常,否則,編譯不通過。
非受查異常(繼承於Error、RuntimeException類的所有異常): 即不檢查異常,程序員也無需寫異常處理的代碼,自動捕獲異常。
Throwable類中的常見方法:

public void printStackTrace(){///打印異常的詳細信息
}///包含異常的類型、異常的原因、異常出現的位置,再開發和調試階段,都得使用printStackTrace

public String getMessage(){///獲取發生異常得原因
}///提示給用戶得時候,就提示錯誤原因

public String toString(){///獲取異常得類型和異常描述信息
}

二、常見的Exception類(運行時和非運行時)異常

在這裏插入圖片描述

三、異常的處理方式

在這裏插入圖片描述

3.1 拋出異常(throw)

在Java中,提供了一個throw關鍵字,且其用在方法內 ,它用來拋出一個指定得異常對象。
步驟: 創建一個異常對象;需要將這個異常對象告知給調用者。

格式: throw new 異常類名(參數)

public class Main {
    public static void main(String [] args){
        int [] arr = {1,3,2,4};
        int n = 4;
        int x = getElment(arr,n);
        System.out.println(x);
    }
    public static int getElment(int []arr,int n){
        if(n<0||n>arr.length-1){
            throw new ArrayIndexOutOfBoundsException("數組越界了");
        }
        int x = arr[n];
        return x;
    }
}

控制檯輸出結果(拋出異常)如下:
在這裏插入圖片描述

3.2 聲明異常(throws)

聲明異常: 將問題標識出來,報告給調用者。如果方法內拋出編譯異常,而沒有捕獲處理,那麼必須通過throws進行聲明,讓調用者去處理。
關鍵字throws 運用於方法聲明之上,用於表示當前方法不處理異常,而是提醒該方法的調用者來處理異常(拋出異常)。通俗地,用在聲明方法時,表示該方法可能要拋出異常。

public void Method() throws Exception1,...{///可以聲明多個異常
 ....
}
3.3 throws和throw的區別
關鍵字 位置不同 作用不同 是否出現異常
throw 用在方法頭(函數體) 表示拋出異常,由方法體內的語句處理,所以它是拋出一個異常實例 執行throw就是一定拋出了某種異常
throws 用在方法聲明後面(函數頭) 表示再拋出異常 ,使它的調用者知道要捕獲這個異常 表示出現異常的一種可能性,並不一定會發生這些異常

共性: 都是消極處理異常的方式(這裏的消極並不是說這種方式不好),只是拋出或者可能拋出異常,但是不會由函數去處理異常,真正的處理異常由函數的上層調用處理。

3.4 捕獲異常(try…catch)

如果異常出現的話,會立刻終止程序,所以我們得處理異常。一個方法所能捕捉的異常,一定是Java代碼在某處所拋出的異常。簡單地說,異常總是先被拋出,後被捕捉
方法處理異常的兩種情況:
1、該方法不處理,而是聲明拋出,由該方法的調用者來處理
2、在方法中使用try-catch 的語句塊來處理異常

try{///該代碼塊中編寫可能產生異常的代碼
...
}catch(異常類型 e){///用來進行某種異常的捕獲,實現對捕獲到的異常進行處理
  處理異常的代碼
  //記錄日誌/打印日常信息/繼續拋出異常
}

try…catch語句: 如果你在方法內部拋出了異常(或在方法內部調用的其他方法拋出了異常),這個方法將拋出異常的過程中結束。這是我們不希望的,所以try塊內將可能發生異常的代碼包起來,稱爲監控區域。Java方法在運行過程中出現異常,則創建異常對象(catch參數所定義的異常)。將異常拋出監控區域之外,由Java運行系統試圖尋找匹配的catch子句以捕獲異常(異常處理程序)。若有匹配的catch子句,則運行其異常處理代碼,try-catch語句結束。

注意:如果在try塊的內部,不同的方法調用可能會產生類型相同的異常,你只需提供一個針對此類型的異常處理程序。

匹配的原則: 如果拋出的異常對象屬於catch子句的異常類,或者屬於該異常類的子類,則認爲生成的異常對象與catch塊捕獲的異常類型相匹配。

3.5 finally代碼塊

有一些特定的代碼無論異常是否發生,都需要執行。另外,因爲異常會引發程序跳轉,導致有些語句執行不到。而finally代碼塊中存放的代碼都是一定被執行的。

try{
  //可能發生異常的程序代碼
}catch(異常類型 e){
 //捕獲並處理try拋出的異常類型
}finally{
 //無論異常是否發生,都將執行
}

try…catch…finally執行順序:
資料來自於https://blog.csdn.net/hguisu/article/details/6155636?utm_source=app&from=singlemessage
1、當try沒有捕獲到異常時:
try語句塊中的語句逐一被執行,程序跳過catch語句塊,執行finally語句塊和其後的語句。
在這裏插入圖片描述
2、當try捕獲到異常時:
· catch語句塊裏沒有處理此異常的情況:此異常將會拋給JVM處理,finally語句還是會被執行,但finally語句塊後的語句不會被執行。
· catch語句塊裏出現處理此異常的情況:當執行某一條語句出現異常時,程序將跳到catch語句塊,並與catch語句塊逐一匹配,找到與之對應的處理程序,其他的catch將不會被執行,而try語句塊中,出現異常之後的語句也不會被執行,catch語句塊執行完後,執行finally語句塊,最後執行其他語句。
在這裏插入圖片描述
什麼時候的代碼塊必須最終執行?
當我們在try語句塊中打開了一些物理資源(磁盤文件/網路連接/數據庫連接等),我們都得在使用完後,最終關閉打開得資源。
finally塊不會被執行的4種特殊情況:
1、在finally語句塊發生異常。
2、前面代碼使用了System.exit()退出程序。
3、程序所在的線程死亡
4、關閉CPU
finally的其他用法
當在try塊或catch塊中遇到return語句時,finally將在返回之前被執行:

public class Main {
    public static void main(String [] args){
       System.out.println(f(2));//輸出0
    }
     public static int f(int x){
        try{
            int n = x*x;
            return n;
        }finally{
            if(x==2) return 0;
        }
     }
}

耦合try/catch和try/finally語句塊

///如果finally子句中出現錯誤時,會報告finally子句中出現的錯誤。
InputStream in = ...;
try{///確保報告出現的錯誤

  try{///確保關閉輸入流
  
  }finally{
   in.close();
  }
}catch(IOException e){
  ...
}
3.6 異常的注意事項

對於有多個catch子句的異常程序來說,應該儘量將捕或底層異常類的catch子句(如:子類)放在前面,同時儘量將捕獲相對高層的異常類的catch子句如:父類)放在後面。否則,捕獲底層異常類的catch子句將可能會被屏蔽。
多個異常使用捕獲情況:
1、多個異常分別處理
2、多個異常一次捕獲,多次處理
3、多個異常一次捕獲一次處理。
一般我們是使用一次捕獲多次處理的方式。

四、自定義異常

爲什麼需要自定義異常類:
上面所學的異常,我們會發現都是JDK內部定義好的,但是實際開發中也會出現很多異常,這些異常很可能在JDK中沒有定義過的,例如年齡的負數問題,考試問題,負數問題,那麼能不能自己定義異常呢?
什麼時自定義異常類:在開發中根據自己的業務異常情況來定義異常類。

五、參考資料

1.https://www.cnblogs.com/xiohao/p/3547443.html
2.https://blog.csdn.net/hguisu/article/details/6155636?utm_source=app&from=singlemessage
3.黑馬程序員

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章