10個關於Java異常的常見問題


這篇文章總結了十個經常被問到的JAVA異常問題;

1.檢查型異常VS非檢查型異常

簡單的說,檢查型異常是指需要在方法中自己捕獲異常處理或者聲明拋出異常由調用者去捕獲處理;

非檢查型異常指那些不能解決的異常,如除0,空指針等;

檢查型異常非常重要,因為你希望使用你API接口的人知道如何處理這些異常;

舉個例子,IOException是非常常見的檢查型異常,RuntimeException是非檢查型異常;

Java的異常層級關系圖如下:

2.異常管理最佳實踐

如果一個異常當前能夠被恰當的處理,那么應該捕獲處理它,否則應該顯示的拋出異常;

3.為什么在try代碼塊里定義的變量,在catch或finally代碼塊里不能被訪問

如下代碼,在try代碼塊中聲明字符串s變量,但是不能在catch代碼塊中使用,代碼不能編譯通過;

        try {
            File file = new File("path");
            FileInputStream fis = new FileInputStream(file);
            String s = "inside";
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println(s);
        }

原因是因為你不知道在try代碼塊中的哪一句會拋出異常,很有可能這個異常在變量聲明之前就拋出了;

這正是以上這個例子的情況;

注:強烈懷疑是因為作用域的關系導致s變量不可見;

4.為什么Integer.parseInt(null)和Double.parseDouble(null)會拋出不同的異常

這是JDK的問題,因為這兩個方法是不同的開發人員寫的,所以沒必要深究;

        Integer.parseInt(null);
        // throws java.lang.NumberFormatException: null
        Double.parseDouble(null);
        // throws java.lang.NullPointerException

注:其實我目前的JDK7已經沒有該問題了,兩個都是拋出NumberFormatException

5.多用運行時異常

幾個常見的運行時異常,如IllegalArgumentException、ArrayIndexOutOfBoundsException;

當判斷條件不滿足時,可以拋出這些異常,如下代碼:

        if (obj == null) {
            throw new IllegalArgumentException("obj can not be null");

6.是否可以在一個catch代碼塊里捕獲多個異常

答案是可以的。因為JAVA的異常可以追溯到同一個父類Exception,我們可以使用父類捕獲多個異常;

        try {
            
        } catch (Exception e) {
            // TODO: handle exception
        }

補充:

在JAVA7中,增加了新語法,可以這樣捕獲多個異常:

try { 
  ...
} catch( IOException | SQLException ex ) { 
  ...
}

在JAVA7之前可以這樣寫:

try {
  //.....
} catch (Exception exc) {
  if (exc instanceof IllegalArgumentException || exc instanceof SecurityException || 
     exc instanceof IllegalAccessException || exc instanceof NoSuchFieldException ) {

     someCode();

  } else if (exc instanceof RuntimeException) {
     throw (RuntimeException) exc;     

  } else {
    throw new RuntimeException(exc);
  }

}

7.構造方法是否可以拋出異常

答案是可以的,構造方法是一個特殊的方法,同樣可以拋出異常;

注意,如果構造方法拋出異常,對象是沒有生成的;

8.finally語句塊同樣可以拋出和捕獲異常

以下代碼是合法的:

    public static void main(String[] args) {
        File file1 = new File("path1");
        File file2 = new File("path2");
        try {
            FileInputStream fis = new FileInputStream(file1);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                FileInputStream fis = new FileInputStream(file2);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

但是出於可讀性考慮,最好把finally里的異常處理代碼封裝到一個方法里,然后調用該方法,如下代碼:

    public static void main(String[] args) {
        File file1 = new File("path1");
        File file2 = new File("path2");
        try {
            FileInputStream fis = new FileInputStream(file1);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            methodThrowException();
        }
    }

9.finally代碼塊里是否可以寫return語句

是的,可以

10.為什么JAVA程序員經常悄悄地忽略異常的處理

以下代碼片段會經常出現在程序中,如果異常處理那么重要,為什么還會有這么多開發人員一直這樣做呢?

        try {
            ...
        } catch (Exception e) {
            e.printStackTrace();
        }

經常出現的代碼並不代表是對的;

可能很多開發人員都使用eclipse的快速修復,自動生成異常處理代碼,如上所示,其實除了記錄下log,並沒有做什么處理;

正如條目2所描述的,如果不能正確處理該異常的話,最好拋出異常,以便異常盡早被發現;

 

譯文鏈接:http://www.programcreek.com/2013/10/top-10-questions-about-java-exceptions/


免責聲明!

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



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