Java異常類型及處理

一、異常定義

異常就是“意外、例外”的意思,也就是非正常情況。異常本質上是程序上的錯誤,包括程序邏輯錯誤和系統錯誤。異常的處理基本上就是用來兜底的,也是程序開發中程序不願意看到的。異常最基本的信息就是線程的堆棧信息。

二、異常的結構和分類

圖片

Throwable主要分為Error和Exception。

錯誤:Error類以及他的子類的實例,代表瞭JVM本身的錯誤。錯誤不能被程序員通過代碼處理,躺平解決就好,不要反抗。常見的錯誤有下面這些

圖片

異常:Exception以及他的子類,代表程序運行時發送的各種不期望發生的事件。可以被Java異常處理機制使用,是異常處理的核心,能在程序中解決的都不叫事。常見的異常有這麼多。

圖片

三、異常的處理和捕獲

異常想要處理肯定要先捕獲到異常才可以,怎麼捕獲異常吶,Java給我提供瞭幾個關鍵字,每個關鍵字怎麼用吶?

1、try,catch 就是直接捕獲異常,catch 內的異常類型是能捕獲的類型,一般如果有多個異常,從上到下的順序是異常范圍越來越大。註:ErrorCodeException的定義可以參考自定義異常。

  public static void second(String[] args) {
      try {
          throw new ErrorCodeException("1123");
      } catch (ErrorCodeException e) {
          e.printStackTrace();
      }catch (Exception e){
          e.printStackTrace();
      }
  }

2、try catch finally 增加瞭finally關鍵字,就是在異常之後還能做一些事情,比如常見的關閉輸入流,輸出流,是程序最後的倔強。

public static String readFileContent(String fileName) {
  File file = new File(fileName);
  BufferedReader reader = null;
  StringBuffer sbf = new StringBuffer();
  try {
      reader = new BufferedReader(new FileReader(file));
      String tempStr;
      while ((tempStr = reader.readLine()) != null) {
          sbf.append(tempStr);
      }
      reader.close();
      return sbf.toString();
  } catch (IOException e) {
      e.printStackTrace();
  } finally {
      if (reader != null) {
          try {
              reader.close();
          } catch (IOException e1) {
              e1.printStackTrace();
          }
      }
  }
  return sbf.toString();
}

3、throw 主要用來創建一個異常,因為程序中可能需要拋出一個異常,比如我們遊戲服務器遊戲邏輯驗證客戶端參數不通過,會主動拋出一個自定義的異常

4、throws 主要用在方法簽名上,當我們讀寫文件或者反射的時候,如果不用try catch 就會發現方法簽名後有一堆的異常需要處理。異常會繼續上拋給上層的調用方法,直至有方法處理或者給系統。

四、自定義異常

當Java內置的異常都不能明確的說明異常情況的時候,需要創建自己的異常。

如果要自定義異常類,則繼承Exception類即可。可以在類中增加一些自己的處理,在創建異常的時候傳入,在處理異常的地方,可以根據具體的內容進行處理。可以看下下面的彈出流程應用。

/**
* @author 香菜
*/
public class ErrorCodeException extends Exception {
   //錯誤碼
   private String errorCode;
   //構造函數
   public ErrorCodeException(String errorCode){
       super(errorCode);
       this.errorCode = errorCode;
  }
   public String getErrorCode() {
       return errorCode;
  }
}

五、異常的應用

在遊戲開發中,每個協議的處理都會驗證參數的是否合理,如果發現參數不合理,我們可以拋出一個自定義的參數異常,在同一的入口處進行捕獲,解析出其中的錯誤碼,直接發給客戶端。避免瞭一層一層的函數返回。

1.打印堆棧

有時候在調試代碼的過程中,因為函數的調用處太多,遊戲不好斷點,我們可以在想要知道函數的調用路徑的情況下,可以隨意拋出一個異常,系統會打印出調用堆棧,幫忙定位問題。是不是又獲得一個小技巧。

/**
* @author 香菜
*/
public class Aain {
   public static void first(String[] args) throws Exception {
       second(args);
  }
   public static void second(String[] args) throws Exception {
       throw new Exception("1123");
  }
   public static void main(String[] args) throws Exception {
           first(args);
  }
}

2.彈出流程

/**
* @author 香菜
*/
public class Aain {
  public static void first(String[] args) throws ErrorCodeException {
      second(args);
  }
  public static void second(String[] args) throws ErrorCodeException {
      third(args);
      System.out.println("1111");
  }
  public static void third(String[] args) throws ErrorCodeException {
      throw new ErrorCodeException("1123");
  }
  public static void main(String[] args){
      try {
          first(args);
      } catch (ErrorCodeException e) {
          e.printStackTrace();
      }
  }
}

圖片

從上面大堆棧打印可以看到,打印的語句沒有執行,在遊戲服務器的消息處理處捕獲一個ErrorCodeException,如果消息處理函數拋出這個異常,在入口處會捕獲並解析其中的錯誤碼返回給客戶端,可以避免一層一層的返回函數

六、註意點

1、Java程序可以是多線程的。每一個線程都是一個獨立的執行流,獨立的函數調用棧。如果程序隻有一個線程,那麼沒有被任何代碼處理的異常 會導致程序終止。如果是多線程的,那麼沒有被任何代碼處理的異常僅僅會導致異常所在的線程結束

2、finally 不具有再次處理異常的能力

3、不要隻捕獲異常而不處理異常,就會發現不瞭問題。

總結

本篇文章就到這裡瞭,希望能給你帶來幫助,也希望您能夠多多關註WalkonNet的更多文章!

推薦閱讀: