10.Java異常問題

目錄介紹

  • 10.0.0.1 見過哪些運行時異常?異常處理機制知道哪些?從異常是否必須須要被處理的角度來看怎麼分類?
  • 10.0.0.2 運用Java異常處理機制?異常處理的原理?Java中檢查異常和非檢查異常的區別?
  • 10.0.0.3 異常處理的過程當中,你遵循那些好的實踐? throw 和 throws這兩個關鍵字在java中有什麼不一樣?
  • 10.0.0.4 你知道什麼是「異常鏈」嗎?自定義實現過哪些異常,怎麼寫的?能夠有一個空的catch塊嗎?
  • 10.0.0.5 Java異常類有哪些的重要方法?致使「主線程中的異常」的不一樣場景是什麼?
  • 10.0.0.6 看下面這段子類繼承父類代碼有什麼問題?針對拋異常是IOException仍是Exception,能隨便寫嗎,結合案例說一下?
  • 10.0.0.7 捕獲異常時,爲什麼在catch中要注意異常層級關係?須要注意哪些問題?

好消息

  • 博客筆記大彙總【15年10月到至今】,包括Java基礎及深刻知識點,Android技術博客,Python學習筆記等等,還包括平時開發中遇到的bug彙總,固然也在工做之餘收集了大量的面試題,長期更新維護而且修正,持續完善……開源的文件是markdown格式的!同時也開源了生活博客,從12年起,積累共計500篇[近100萬字],將會陸續發表到網上,轉載請註明出處,謝謝!
  • 連接地址:https://github.com/yangchong211/YCBlogs
  • 若是以爲好,能夠star一下,謝謝!固然也歡迎提出建議,萬事起於忽微,量變引發質變!全部博客將陸續開源到GitHub!

10.0.0.1 見過哪些運行時異常?異常處理機制知道哪些?從異常是否必須須要被處理的角度來看怎麼分類?

  • 運行時異常:Throwable繼承層次結構,可見分紅兩大類Error和Exception:
    • Error(錯誤):指程序沒法恢復的異常狀況,表示運行應用程序中較嚴重的問題;發生於虛擬機自身、或者在虛擬機試圖執行應用時,如Virtual MachineError(Java虛擬機運行錯誤)、NoClassDefFoundError(類定義錯誤);屬於不可查異常,即不強制程序員必須處理,即便不處理也不會出現語法錯誤。
    • Exception(異常):指程序有可能恢復的異常狀況,表示程序自己能夠處理的異常。又分兩大類:
      • RuntimeException(運行時異常):由程序自身的問題致使產生的異常;如NullPointerException(空指針異常)、IndexOutOfBoundsException(下標越界異常);屬於不可查異常。
      • 非運行時異常:由程序外部的問題引發的異常;除了RuntimeException之外的異常,如FileNotFoundException(文件不存在異常);屬於可查異常,即強制程序員必須進行處理,若是不進行處理則會出現語法錯誤。
  • 異常處理機制
    • 捕捉異常:由系統自動拋出異常,即try捕獲異常->catch處理異常->finally 最終處理
    • 拋出異常:在方法中將異常對象顯性地拋出,以後異常會沿着調用層次向上拋出,交由調用它的方法來處理。配合throws聲明拋出的異常和throw拋出異常
    • 自定義異常:繼承Execption類或其子類
    • 技術博客大總結
  • 從異常是否必須須要被處理的角度來看怎麼分類
    • 異常又可分爲不受檢查異常和受檢查異常兩種狀況:
      • 不受檢查異常:派生於 Error 或 RuntimeException 的全部異常;
      • 受檢查異常:除去不受檢查異常的全部異常。
      • image

10.0.0.2 運用Java異常處理機制? 異常處理的原理?Java中檢查異常和非檢查異常的區別?

  • 運用Java異常處理機制?
    • 1.try…catch語句
    • 2.finally語句:大多數狀況下都必須執行的代碼
    • 3.throws子句:聲明可能發生的異常類
    • 4.throw:拋出具體的異常對象。
  • 異常處理的原理?
    • Java虛擬機用方法調用棧(method invocation stack)來跟蹤每一個線程中一系列的方法調用過程。若是在執行方法過程當中拋出異常,則Java虛擬機必須找到能捕獲該異常的catch代碼塊。當Java虛擬機追溯到調用棧的底部的方法的時候,若是仍然沒有找處處理該異常的代碼塊,這樣它就會按步驟處理,首先會打印方法調用棧的異常信息,而後若是所處的線程不是主線程,那麼就會終止這個線程。
  • Java中檢查異常和非檢查異常的區別
    • 檢查型異常(CheckedException)
      • 在Java中全部不是RuntimeException派生的Exception都是檢查型異常。當函數中存在拋出檢查型異常的操做時該函數的函數聲明中必須包含throws語句。調用改函數的函數也必須對該異常進行處理,如不進行處理則必須在調用函數上聲明throws語句。
      • 檢查型異常是JAVA獨創的,在編譯期對異常的處理有強制性的要求。在JDK代碼中大量的異常屬於檢查型異常,包括IOException,SQLException等等。
    • 非檢查型異常(UncheckedException)技術博客大總結
      • 在Java中全部RuntimeException的派生類都是非檢查型異常,與檢查型異常對比,非檢查型異常能夠不在函數聲明中添加throws語句,調用函數上也不須要強制處理。
      • 常見的NullPointException,ClassCastException是常見的非檢查型異常。非檢查型異常能夠不使用try…catch進行處理,可是若是有異常產生,則異常將由JVM進行處理。對於RuntimeException的子類最好也使用異常處理機制。雖然RuntimeException的異常能夠不使用try…catch進行處理,可是若是一旦發生異常,則確定會致使程序中斷執行,因此,爲了保證程序再出錯後依然能夠執行,在開發代碼時最好使用try…catch的異常處理機制進行處理。

10.0.0.3 異常處理的過程當中,你遵循那些好的實踐? throw 和 throws這兩個關鍵字在java中有什麼不一樣?

  • 異常處理的過程當中,你遵循那些好的實踐?
    • 異常處理在項目設計中是很是關鍵的,因此精通異常處理是十分必要的。異常處理有不少最佳實踐,下面列舉集中,它們提升你代碼的健壯性和靈活性:
    • 1) 調用方法的時候返回布爾值來代替返回null,這樣能夠 NullPointerException。因爲空指針是java異常裏最噁心的異常。
    • 2) catch塊裏別不寫代碼。空catch塊是異常處理裏的錯誤事件,由於它只是捕獲了異常,卻沒有任何處理或者提示。一般你起碼要打印出異常信息,固然你最好根據需求對異常信息進行處理。
    • 3)能拋受控異常(checked Exception)就儘可能不拋受非控異常(checked Exception)。經過去掉重複的異常處理代碼,能夠提升代碼的可讀性。
    • 4) 絕對不要讓你的數據庫相關異常顯示到客戶端。因爲絕大多數數據庫和SQLException異常都是受控異常,在Java中,你應該在DAO層把異常信息處理,而後返回處理過的能讓用戶看懂並根據異常提示信息改正操做的異常信息。
    • 5) 在Java中,必定要在數據庫鏈接,數據庫查詢,流處理後,在finally塊中調用close()方法。
  • throw 和 throws這兩個關鍵字在java中有什麼不一樣?
    • 技術博客大總結
    • throws老是出如今一個函數頭中,用來標明該成員函數可能拋出的各類異常,你也能夠申明未檢查的異常,但這不是編譯器強制的。若是方法拋出了異常那麼調用這個方法的時候就須要將這個異常處理。
    • throw 是用來拋出任意異常的,按照語法你能夠拋出任意 Throwable (Throwable 或任何Throwable的衍生類) , throw能夠中斷程序運行,所以能夠用來代替return。
      private static voidshow() {  
      throw new UnsupportedOperationException(「拋出異常」);
      }

10.0.0.4 你知道什麼是「異常鏈」嗎?自定義實現過哪些異常,怎麼寫的?能夠有一個空的catch塊嗎?

  • 你知道什麼是「異常鏈」嗎?
    • 「異常鏈」是Java中很是流行的異常處理概念,是指在進行一個異常處理時拋出了另一個異常,由此產生了一個異常鏈條。該技術大多用於將「 受檢查異常」 ( checked exception)封裝成爲「非受檢查異常」(unchecked exception)或者RuntimeException。順便說一下,若是由於由於異常你決定拋出一個新的異常,你必定要包含原有的異常,這樣,處理程序才能夠經過getCause()和initCause()方法來訪問異常最終的根源。
  • 自定義實現過哪些異常?
  • 能夠有一個空的catch塊嗎?
    • 能夠有一個空的catch塊,但這是最糟糕的編程的例子。不該該有空的catch塊,由於若是異常被該塊捕獲,咱們將沒有關於異常的信息,它將成爲調試它的噩夢。應該至少有一個日誌記錄語句來記錄控制檯或日誌文件中的異常詳細信息。
    • 技術博客大總結

10.0.0.5 Java異常類有哪些的重要方法?致使「主線程中的異常」的不一樣場景是什麼?

  • Java異常類有哪些的重要方法?
    • Exception和它的全部子類沒有提供任何特殊方法供使用,它們的全部方法都是來自其基類Throwable。
      • String getMessage():方法返回Throwable的String型信息,當異常經過構造器建立後可用。
      • String getLocalizedMessage():此方法經過被重寫來獲得用本地語言表示的異常信息返回給調用程序。Throwable類一般只是用getMessage()方法來實現返回異常信息。
      • synchronized Throwable getCause():此方法返回異常產生的緣由,若是不知道緣由的話返回null。(原文有拼寫錯誤 應該是if 不是id)
      • String toString():方法返回String格式的Throwable信息,此信息包括Throwable的名字和本地化信息。
      • void printStackTrace():該方法打印棧軌跡信息到標準錯誤流。該方法能接受PrintStream 和PrintWriter做爲參數實現重載,這樣就能實現打印棧軌跡到文件或流中。
  • 致使「主線程中的異常」的不一樣場景是什麼?
    • 一些常見的主線程異常狀況是:
      • 線程main java.lang.UnsupportedClassVersionError中的異常:當您的java類從另外一個JDK版本編譯而且您試圖從另外一個java版本運行它時,會出現此異常。
      • 線程main java.lang.NoClassDefFoundError中的異常 :此異常有兩種變體。 第一個是你提供擴展名爲.class的類全名的地方。 第二種狀況是沒有找到類。
      • 線程main java.lang.NoSuchMethodError中的異常:main :當您嘗試運行一個沒有main方法的類時,會出現此異常。
      • 技術博客大總結
      • 線程「main」中的異常java.lang.ArithmeticException :不管什麼時候從main方法拋出任何異常,它都會打印出異常是console。 第一部分解釋了異常從main方法拋出,第二部分打印異常類名稱,而後在冒號後打印異常消息。

10.0.0.6 看下面這段子類繼承父類代碼有什麼問題?針對拋異常是IOException仍是Exception,能隨便寫嗎,結合案例說一下?

  • 看下面這段代碼有什麼問題?php

    public class SuperClass {  
        public void start() throws IOException{
            throw new IOException("Not able to open file");
        }
    }
    
    public class SubClass extends SuperClass{  
        public void start() throws Exception{
            throw new Exception("Not able to start");
        }
    }
    • 這段代碼編譯器將對子類覆蓋start方法產生錯誤。由於每一個Java中方法的覆蓋是有規則的,一個覆蓋的方法不能拋出的異常比原方法繼承關係高。由於這裏的start方法在超類中拋出了IOException,全部在子類中的start方法只能拋出要麼是IOExcepition或是其子類,但不能是其超類,如Exception。
  • 針對拋異常是IOException仍是Exception,能隨便寫嗎,結合案例說一下?java

    • 確定不要隨便寫,容易形成迷惑性。下面看看代碼,舉個簡單的案例!技術博客大總結
      public static void start(){
      System.out.println("Java Exception");
      }

    public static void main(String args[]) {
    try{
    start();
    }catch(IOException e){
    e.printStackTrace();
    }
    }git

    - 上面的Java異常例子代碼中,編譯器將在處理IOException時報錯,由於IOException是受檢查異常,而start方法並無拋出IOException,因此編譯器將拋出「異常,java.io.IOException不會在try語句體中拋出」,可是若是你將IOException改成Exception,編譯器報錯將消失,由於Exception能夠用來捕捉全部運行時異常,這樣就不須要聲明拋出語句。我喜歡這樣帶有迷惑性的Java異常面試題,由於它不會讓人輕易的找出是IOException仍是Exception。你也能夠在JoshuaBloach和NeilGafter的Java謎題中找到一些有關Java錯誤和異常的具備迷惑性問題。

10.0.0.7 捕獲異常時,爲什麼在catch中要注意異常層級關係?須要注意哪些問題?

  • 捕獲異常時,爲什麼在catch中要注意異常層級關係?須要注意哪些問題?程序員

    • 注意,catch中必定要注意層級關係。這裏舉一個簡單的案例,就能夠很好的理解爲什麼要注重層級問題呢!
    • 技術博客大總結
      public static void start() throws IOException, RuntimeException{
      throw new RuntimeException("Not able to Start");
      }

    public static void main(String args[]) {
    try {
    start();
    } catch (Exception e) {
    e.printStackTrace();
    } catch (RuntimeException e2) {
    e2.printStackTrace();
    }
    }github

    - 這段代碼會在捕捉異常代碼塊的RuntimeException類型變量「e2」裏拋出編譯異常錯誤。由於Exception是RuntimeException的超類,在start方法中全部的RuntimeException會被第一個捕捉異常塊捕捉,這樣就沒法到達第二個捕捉塊,這就是拋出「exception java.lang.RuntimeException has already been caught」的編譯錯誤緣由。

其餘介紹

01.關於博客彙總連接

02.關於個人博客

相關文章
相關標籤/搜索