開發(fā)筆記之詳解JAVA異常的前世今生

我原本是個快樂的iOS開發(fā)者, 總是會看到一張圖片:


拋出異常

我就在想crash就crash了唄, 弄這么多學名干嘛, 還拋出異常. 后來經過我對JAVA的研究我發(fā)現我的想法被啪啪打臉, 那叫一個左右開弓.
( ̄ε(# ̄)☆╰╮( ̄▽ ̄///)
還是我太naive, 而今天, 就要詳述一下異常這個東西.


我們要確立一個概念, 那就是: 什么是異常機制.

異常機制是指當程序出現錯誤后,程序如何處理。具體來說,異常機制提供了程序退出的安全通道。當出現錯誤后,程序執(zhí)行的流程發(fā)生改變,程序的控制權轉移到異常處理器。

當你明白異常機制是怎么回事的時候,異常處理的流程你也不難接受.

當程序中拋出一個異常后,程序從程序中導致異常的代碼處跳出,java虛擬機檢測尋找和try關鍵字匹配的處理該異常的catch塊,如果找到,將控制權交到catch塊中的代碼,然后繼續(xù)往下執(zhí)行程序,try塊中發(fā)生異常的代碼不會被重新執(zhí)行。如果沒有找到處理該異常的catch塊,在所有的finally塊代碼被執(zhí)行和當前線程的所屬的ThreadGroup的uncaughtException方法被調用后,遇到異常的當前線程被中止。

用代碼表示就是:

        try {
            System.out.println("尋找到try關鍵字");
        } catch (Exception e){
            e.printStackTrace();
            System.out.println("捕獲異常");
        } finally {
            System.out.println("無論走try還是走catch, finally中的代碼都會被執(zhí)行");
        }

java.lang.Throwable

既然要說明白異常的前世今生就要先說一說這些異常的前世, java.lang.Throwable是 Java 中所有錯誤或異常的超類。只有當對象是此類(或其子類之一)的實例時,才能通過 JVM 或者 Java throw 語句來拋出, 換言之, 所有的異常都是從他這出來的, 他是所有異常的祖宗類.
而且, 類似的, 只有此類或其子類之一才可以是 catch 子句中的參數類型.


常見的異常之間的關系

由圖可見, 他有兩個子類, 這兩個子類就是區(qū)別開了兩種不同的異常.


第一種.java.lang.Error

Error是 Throwable 的子類,用于指示合理的應用程序不應該試圖捕獲的嚴重問題, 這個問題有多嚴重? 十分嚴重, 不可恢復的錯誤, 這種情況下的程序只能終止運行, 但是要注意一點的是, 編譯器不會檢查Error是不是被處理, 程序中也不用捕獲Error類型的異常, 一般情況下, 程序中也是絕對不應該拋出這種異常的, 但是一旦出現Error必須修改源代碼.

第二種.java.lang. Exception

Exception是由JVM發(fā)出的異常, 他的異常類型包括兩種, 一種是RuntimeException, 另外一種是Checked Exception異?;蛘哒f是(記成)非RuntimeException類型的異常也可.

RuntimeException類型的異常是很特殊的, 他是一種Unchecked Exception, 編譯器不會檢查程序是不是處理了RuntimeException, 在程序中也不去捕獲RuntimeException類型的異常, 也不會再方法體中拋出RuntimeException. RuntimeException類型的異常出現的時候表示程序中出現了邏輯編程錯誤, 作為程序員應該找出錯誤并且修改.

Checked Exception異常, 或者說是非RuntimeException類型的異常, 是Exception異常種類中除了RuntimeException異常就是他了, 而JAVA規(guī)定了所有的Checked Exception異常都要處理, 編譯器也會檢查這種異常是否存在, 要么拋出, 要么try catch捕獲, 處理, 否則將不能通過編譯.


出現異常怎么辦

對于異常, 真正有用的是意向的對象類型, 而不是異常對象本身, 每一種異常對象都有著自己的含義, 老規(guī)矩, 為了便于理解, 上代碼!

    public static double div(int a, int b){
        return a / b;
    }
    // 然后調用
    div(4, 0);

顯而易見的, 我們犯了一個很基礎的錯誤, 那就是拿一個整數去除以0, 當然, 我們親愛的JAVA不會慣著我們.

又拋出異常

我們來看一下拋出的異常信息.

異常信息

在這里我們會看到幾處有意思的東西.

  1. java.lang.ArithmeticException 這個東西好像是類?
  2. by zero 我好像是除以0了.
  3. at com.company.Main.div(Main.java:69)
    at com.company.Main.main(Main.java:28) 這兩行.

我們首先來看看java.lang.ArithmeticException, 這個類的意思是當出現異常的運算條件時,拋出此異常。就比如說我們所做的,一個整數“除以零”時,拋出此類的一個實例.

然后再看 by zero, 的確是除以0了, 沒毛病.

最后再看最后這兩行東西, div和main好像是你的兩個方法, Main是不是主入口呢? 你看了一下 69 行和 28 行

   return a/b; // 69行
   div(4, 0); // 28行

大呼神奇.
現在你能看懂異常了.


自定義異常

你以為看懂異常就結束了嗎? naive, 你不但要會看, 你還要會寫, 編程瞬息萬變, 你怎么能確定JAVA就考慮到所有你可能出錯的情況呢? 所以, 當JAVA內置的異常都不能明確的說明異常情況的時候,需要創(chuàng)建自己的異常.
但是你需要注意的是, 唯一有用的就是類型名這個信息,所以不要在異常類的設計上花費精力, 他只是去給你提供一個信息的.
還是上代碼來的清楚, 請看.

class Computer {
    public String getStatus() {
        return status;
    }

    public void setStatus(String status) throws DownException, EnterWaterException {
        this.status = status;
        if (status.equals("進水")){
            throw new EnterWaterException("進水了, 燒了");
        } else if (status.equals("摔了")){
            throw new DownException("摔了, 有錢了");
        }
    }
    private  String status;
}

class DownException extends RuntimeException{
    public DownException(String message){
        super(message);
    }
}

class EnterWaterException extends RuntimeException{
    public EnterWaterException(String message){
        super(message);
    }
}

你可以清晰的看到我新建了兩個異常, 并把他放入一個叫做Computer的類中, 并讓 setStatus方法接著向上拋出異常.

        Computer computer = new Computer();
        try {
            computer.setStatus("進水");
        } catch (EnterWaterException e){
            e.printStackTrace();
        } catch (DownException e){
            e.printStackTrace();
        } finally {
            System.out.println("finally");
        }

然后我try catch了異常. 來看一下輸出的結果.

異常信息

怎么樣, 是不是結果顯而易見, 但是這里有幾點需要注意一下, 并且要記住.

  1. 對于應該在聲明方法拋出異常還是在方法中捕獲異常, 我們應該遵守一個原則, 捕捉并處理哪些知道如何處理的異常,而傳遞哪些不知道如何處理的異常
  2. 多個異常捕獲, 異常對象存在父子關系是, 要求父類型的異常, 寫在子類的下面
  3. 多個異??梢院喜⒃谝粋€catch中 catch(Exception e), 但是為了看著清晰我沒有這么做.
  4. throws 是聲明這個方法的調用存在異常情況, 調用者需采取捕獲處理或繼續(xù)向外拋的操作才能通過編譯
  5. 當代碼出現問題時, JVM會創(chuàng)建一個異常對象并拋個調用者
  6. 調用者接收到異常之后不能處理, 繼續(xù)往上拋直到拋給JVM, 最終將異常信息輸出到控制臺
最后輸出到控制臺

這里是一些常見的異常, 方便與在大家在拋出異常的時候來對照:

ArithmeticException——由于除數為0引起的異常;
ArrayStoreException——由于數組存儲空間不夠引起的異常;
ClassCastException—一當把一個對象歸為某個類,但實際上此對象并不是由這個類 創(chuàng)建的,也不是其子類創(chuàng)建的,則會引起異常;
IllegalMonitorStateException——監(jiān)控器狀態(tài)出錯引起的異常;
NegativeArraySizeException—一數組長度是負數,則產生異常;
NullPointerException—一程序試圖訪問一個空的數組中的元素或訪問空的對象中的 方法或變量時產生異常;
OutofMemoryException——用new語句創(chuàng)建對象時,如系統(tǒng)無法為其分配內存空 間則產生異常;
SecurityException——由于訪問了不應訪問的指針,使安全性出問題而引起異常;
IndexOutOfBoundsExcention——由于數組下標越界或字符串訪問越界引起異常;
IOException——由于文件未找到、未打開或者I/O操作不能進行而引起異常;
ClassNotFoundException——未找到指定名字的類或接口引起異常;
CloneNotSupportedException——一程序中的一個對象引用Object類的clone方法,但 此對象并沒有連接Cloneable接口,從而引起異常;
InterruptedException—一當一個線程處于等待狀態(tài)時,另一個線程中斷此線程,從 而引起異常;
NoSuchMethodException一所調用的方法未找到,引起異常;
IllegalAccessExcePtion—一試圖訪問一個非public方法;
StringIndexOutOfBoundsException——訪問字符串序號越界,引起異常;
ArrayIdexOutOfBoundsException—一訪問數組元素下標越界,引起異常;
NumberFormatException——字符的UTF代碼數據格式有錯引起異常;
IllegalThreadException—一線程調用某個方法而所處狀態(tài)不適當,引起異常;
FileNotFoundException——未找到指定文件引起異常;
EOFException——未完成輸入操作即遇文件結束引起異常。


怎么樣, 大家是不是對于異常都已經有了自己的理解了呢, 希望大家要達道下圖的水平.


解決異常

我們作為程序員, 每天都在想的無非就是我怎么把代碼敲得更牛逼, 更美觀, 而我一直認為知識, 見解, 經驗的分享和學習是自我進行學習的一個重要的途徑, 所以, 知識的分享總會增值, 非常期待與各位看官切磋想法, 交流心得.

個人其他文章:
個人編程想法心得(不定期更新)
開發(fā)筆記之詳述JAVA構造函數和代碼塊本身及其執(zhí)行細節(jié)
開發(fā)筆記之冒泡排序, 選擇排序, 折半查找
iOS開發(fā)筆記-基于AFNetworking 3.0的登錄 注冊
開發(fā)筆記之JAVA String StringBuffer StringBuilder
開發(fā)筆記之JAVA ArrayList 和 LinkedList

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 通俗編程——白話JAVA異常機制 - 代碼之道,編程之法 - 博客頻道 - CSDN.NEThttp://blog...
    葡萄喃喃囈語閱讀 3,325評論 0 25
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,628評論 18 399
  • 六種異常處理的陋習 你覺得自己是一個Java專家嗎?是否肯定自己已經全面掌握了Java的異常處理機制?在下面這段代...
    Executing閱讀 1,410評論 0 6
  • Java異常 異常指不期而至的各種狀況,如:文件找不到、網絡連接失敗、非法參數等。異常是一個事件,它發(fā)生在程序運行...
    java部落閱讀 3,595評論 1 13
  • 人啊,總是善變的。留下那些深淺不一的傷疤,還在提醒著,早已不在他心尖,又何必去追。 “分手吧!” 冰冷的屏幕上發(fā)來...
    素人小子閱讀 296評論 2 2

友情鏈接更多精彩內容