異常(Exception)


JavaSE

異常(Exception)

什么是異常

  • 實際工作中,遇到的情況不可能是非常完美的。比如:你寫的某個模塊,用戶輸入不一定符合你的要求、你的程序要打開某個文件,這個文件可能不存在或者文件格式不對,你要讀取數據庫的數據,數據可能是空的等。我們的程序再跑着,內存或硬盤可能滿了。等等。

  • 軟件程序在運行過程中,非常可能遇到剛剛提到的這些異常問題,我們叫異常,英文是:
    Exception,意思是例外。這些,例外情況,或者叫異常,怎么讓我們寫的程序做出合理的處理。而不至於程序崩潰。

  • 異常指程序運行中出現的不期而至的各種狀況,如:文件找不到、網絡連接失敗、非法參數等。

  • 異常發生在程序運行期間,它影響了正常的程序執行流程。

  • public class Demo01 {
        public static void main(String[] args) {
            new Demo01().a();
        }
        public void a(){
            b();
        }
        public void b(){
            a();
        }
      }
    
    //Exception in thread "main" java.lang.StackOverflowError
    
  • public static void main(String[] args) {
            System.out.println(11/0);
        }
    
    //Exception in thread "main" java.lang.ArithmeticException: / by zero
    

簡單分類

  • 要理解Java異常處理是如何工作的,你需要掌握以下三種類型的異常:
  • 檢查性異常:最具代表的檢查性異常是用戶錯誤或問題引起的異常,這是程序員無法預見的。例如要打開一個不存在文件時,一個異常就發生了,這些異常在編譯時不能被簡單地忽略。
  • 運行時異常:運行時異常是可能被程序員避免的異常。與檢查性異常相反,運行時異常可以在編譯時被忽略。
  • 錯誤:錯誤不是異常,而是脫離程序員控制的問題。錯誤在代碼中通常被忽略。例如,當棧溢出時,一個錯誤就發生了,它們在編譯也檢查不到的。

異常體系結構

  • Java把異常當作對象來處理,並定義一個基類java.lang.Throwable作為所有異常的超類。
  • 在Java API中已經定義了許多異常類,這些異常類分為兩大類,錯誤Error和異常Exception

Error

  • Error類對象由Java虛擬機生成並拋出,大多數錯誤與代碼編寫者所執行的操作無關。

  • Java虛擬機運行錯誤(Virtual MachineError),當JVM不再有繼續執行操作所需的內存資源時,將出現OutOfMemoryError。這些異常發生時,Java虛擬機(JVM)一般會選擇線程終止。

  • 還有發生在虛擬機試圖執行應用時,如類定義錯誤(NoClassDefFoundError)、鏈接錯誤(LinkageError)。這些錯誤是不可查的,因為它們在應用程序的控制和處理能力之外,而且絕大多數是程序運行時不允許出現的狀況。

Exception

  • 在Exception分支中有一個重要的子類RuntimeException(運行時異常)
    • ArraylndexOutOfBoundsException(數組下標越界)
    • NullPointerException(空指針異常)
    • ArithmeticException(算術異常)
    • MissingResourceException(丟失資源)
    • ClassNotFoundException(找不到類)等異常,這些異常是不檢查異常,程序中可以選擇捕獲處理,也可以不處理。
  • 這些異常一般是由程序邏輯錯誤引起的,程序應該從邏輯角度盡可能避免這類異常的發生。
  • Error和Exception的區別:Error通常是災難性的致命的錯誤,是程序無法控制和處理的,當出現這些異常時,Java虛擬機(JVM)一般會選擇終止線程;Exception通常情況下是可以被程序處理的,並且在程序中應該盡可能的去處理這些異常。

Java異常處理機制

  • 拋出異常

  • 捕獲異常

  • 異常處理五個關鍵字

    • try,catch,finnally,throw,throws
  • public static void main(String[] args) {
            int a=1;
            int b=0;
            try {//try監控區域
                System.out.println(a/b);
            }catch (ArithmeticException e){//catch(想要捕獲的異常類型!)  捕獲異常
                System.out.println("Exception,變量b不能為0");
            }finally {//處理善后工作
                System.out.println("finally");
            }
        }
     //finally 可以不要finally ,假設IO,資源,關閉!
    //Throwable 最高
    
  •  public static void main(String[] args) {
            int a=1;
            int b=0;
            //假設要捕獲多個異常:從小到大
            try {//try監控區域
                System.out.println(a/b);
            }catch (Error e){
                System.out.println("Error");
            }catch (Exception e){
                System.out.println("Exception");
            }catch (Throwable e){
                System.out.println("Throwable");
            } finally {//處理善后工作
                System.out.println("finally");
            }
            //finally 可以不要finally ,假設IO,資源,關閉!
        }
    }
    
  • 快捷鍵 Ctrl+Alt+T(Surround with)

  • public static void main(String[] args) {
           int a=1;
           int b=0;
           //Ctrl+Alt+T
            try {
                System.out.println(a/b);
            } catch (Exception e) {
                e.printStackTrace();//打印錯誤的棧信息
            }
            try {
                if(b==0){// throw throws
                    throw new ArithmeticException();//主動的拋出異常
                }
            }catch (Exception e){
                System.out.println("Exception");
            }finally {
                System.out.println("finally ");
            }
    }
    
  • public class Demo01 {
        public static void main(String[] args) {
            try {
                new Demo01().test(1,0);
            } catch (ArithmeticException e) {
                e.printStackTrace();
            }
        }
        public void test(int a, int b) throws ArithmeticException{
            if (b == 0) {// throw throws
                throw new ArithmeticException();
                //主動的拋出異常,一般在方法中使用
            }
            System.out.println(a/b);
        }
    }
    

自定義異常

  • 使用Java內置的異常類可以描述在編程時出現的大部分異常情況。除此之外,用戶還可以自定義異常。用戶自定義異常類,只需繼承Exception類即可。

  • 在程序中使用自定義異常類,大體可分為以下幾個步驟:

    • 創建自定義異常類。

    • 在方法中通過throw關鍵字拋出異常對象。

    • 如果在當前拋出異常的方法中處理異常,可以使用try-catch語句捕獲並處理;否則在方法的聲明處通過throws關鍵字指明要拋出給方法調用者的異常,繼續進行下一步操作。

    • 在出現異常方法的調用者中捕獲並處理異常。

    • public class TestMyException{
          //可能會存在異常的方法
          static void test(int a) throws MyException{
              if (a>10) {
                  throw new MyException(a);//拋出
              }
              System.out.println("OK");
          }
      
          public static void main(String[] args) {
              try {
                  test(11);
              } catch (MyException e) {
                  //增加一些處理異常的代碼
                  ......
                  System.out.println("MyException=>"+e);
              }
          }
      }
      
    • //自定義異常類
      public class MyException extends Exception{
         //傳遞數字>10
          private int detail;
          public MyException(int a){
              this.detail=a;
          }
          //toString:異常的打印信息
          @Override
          public String toString() {
              return "MyException{" + detail + '}';
          }
      }
      

總結

  • 處理運行時異常時,采用邏輯去合理規避同時輔助 try-catch處理。
  • 在多重catch塊后面,可以加一個catch(Exception)來處理可能會被遺漏的異常。
  • 對於不確定的代碼,也可以加上try-catch,處理潛在的異常。
  • 盡量去處理異常,切忌只是簡單地調用printStackTrace()去打印輸出。
  • 具體如何處理異常,要根據不同的業務需求和異常類型去決定。
  • 盡量添加finally語句塊去釋放占用的資源。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM