天天看點

JAVA異常情況如何處理?

Java異常類層次結構?

  • Throwable 是 Java 語言中所有錯誤與異常的超類。
  • Error 類及其子類:程式中無法處理的錯誤,表示運作應用程式中出現了嚴重的錯誤。
  • Exception 程式本身可以捕獲并且可以處理的異常。Exception 這種異常又分為兩類:運作時異常和編譯時異常。
JAVA異常情況如何處理?
  • 運作時異常

都是RuntimeException類及其子類異常,如NullPointerException(空指針異常)、IndexOutOfBoundsException(下标越界異常)等,這些異常是不檢查異常,程式中可以選擇捕獲處理,也可以不處理。這些異常一般是由程式邏輯錯誤引起的,程式應該從邏輯角度盡可能避免這類異常的發生。

運作時異常的特點是Java編譯器不會檢查它,也就是說,當程式中可能出現這類異常,即使沒有用try-catch語句捕獲它,也沒有用throws子句聲明抛出它,也會編譯通過。

  • 非運作時異常 (編譯異常)

是RuntimeException以外的異常,類型上都屬于Exception類及其子類。從程式文法角度講是必須進行處理的異常,如果不處理,程式就不能編譯通過。如IOException、SQLException等以及使用者自定義的Exception異常,一般情況下不自定義檢查異常。

可查的異常(checked exceptions)和不可查的異常(unchecked exceptions)差別?

  • 可查異常(編譯器要求必須處置的異常):

正确的程式在運作中,很容易出現的、情理可容的異常狀況。可查異常雖然是異常狀況,但在一定程度上它的發生是可以預計的,而且一旦發生這種異常狀況,就必須采取某種方式進行處理。

除了RuntimeException及其子類以外,其他的Exception類及其子類都屬于可查異常。這種異常的特點是Java編譯器會檢查它,也就是說,當程式中可能出現這類異常,要麼用try-catch語句捕獲它,要麼用throws子句聲明抛出它,否則編譯不會通過。

  • 不可查異常(編譯器不要求強制處置的異常)

包括運作時異常(RuntimeException與其子類)和錯誤(Error)。

throw和throws的差別?

  • 異常的申明(throws)

在Java中,目前執行的語句必屬于某個方法,Java解釋器調用main方法執行開始執行程式。若方法中存在檢查異常,如果不對其捕獲,那必須在方法頭中顯式聲明該異常,以便于告知方法調用者此方法有異常,需要進行處理。 在方法中聲明一個異常,方法頭中使用關鍵字throws,後面接上要聲明的異常。若聲明多個異常,則使用逗号分割。如下所示:

public static void method() throws IOException, FileNotFoundException{
    //something statements
}      
  • 異常的抛出(throw)

如果代碼可能會引發某種錯誤,可以建立一個合适的異常類執行個體并抛出它,這就是抛出異常。如下所示:

public static double method(int value) {
    if(value == 0) {
        throw new ArithmeticException("參數不能為0"); //抛出一個運作時異常
    }
    return 5.0 / value;
}      

Java 7 的 try-with-resource?

如果你的資源實作了 AutoCloseable 接口,你可以使用這個文法。大多數的 Java 标準資源都繼承了這個接口。當你在 try 子句中打開資源,資源會在 try 代碼塊執行後或異常處理後自動關閉。

public void automaticallyCloseResource() {
    File file = new File("./tmp.txt");
    try (FileInputStream inputStream = new FileInputStream(file);) {
        // use the inputStream to read a file
    } catch (FileNotFoundException e) {
        log.error(e);
    } catch (IOException e) {
        log.error(e);
    }
}      

異常的底層?

提到JVM處理異常的機制,就需要提及Exception Table,以下稱為異常表。我們暫且不急于介紹異常表,先看一個簡單的 Java 處理異常的小例子。

public static void simpleTryCatch() {
   try {
       testNPE();
   } catch (Exception e) {
       e.printStackTrace();
   }
}      

使用javap來分析這段代碼(需要先使用javac編譯)

//javap -c Main
 public static void simpleTryCatch();
    Code:
       0: invokestatic  #3                  // Method testNPE:()V
       3: goto          11
       6: astore_0
       7: aload_0
       8: invokevirtual #5                  // Method java/lang/Exception.printStackTrace:()V
      11: return
    Exception table:
       from    to  target type
           0     3     6   Class java/lang/Exception      

看到上面的代碼,應該會有會心一笑,因為終于看到了Exception table,也就是我們要研究的異常表。

  • from 可能發生異常的起始點
  • to 可能發生異常的結束點
  • target 上述from和to之前發生異常後的異常處理者的位置
  • type 異常處理者處理的異常的類資訊