這篇文章總結了十個經常被問到的JAVA異常問題;
簡單的說,檢查型異常是指需要在方法中自己捕獲異常處理或者聲明拋出異常由調用者去捕獲處理;
非檢查型異常指那些不能解決的異常,如除0,空指針等;
檢查型異常非常重要,因為你希望使用你API接口的人知道如何處理這些異常;
舉個例子,IOException是非常常見的檢查型異常,RuntimeException是非檢查型異常;
Java的異常層級關系圖如下:

如果一個異常當前能夠被恰當的處理,那麼應該捕獲處理它,否則應該顯示的拋出異常;
如下代碼,在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變量不可見;
這是JDK的問題,因為這兩個方法是不同的開發人員寫的,所以沒必要深究;
Integer.parseInt(null);
// throws java.lang.NumberFormatException: null
Double.parseDouble(null);
// throws java.lang.NullPointerException
注:其實我目前的JDK7已經沒有該問題了,兩個都是拋出NumberFormatException
幾個常見的運行時異常,如IllegalArgumentException、ArrayIndexOutOfBoundsException;
當判斷條件不滿足時,可以拋出這些異常,如下代碼:
if (obj == null) {
throw new IllegalArgumentException("obj can not be null");
答案是可以的。因為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);
}
}
答案是可以的,構造方法是一個特殊的方法,同樣可以拋出異常;
注意,如果構造方法拋出異常,對象是沒有生成的;
以下代碼是合法的:
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();
}
}
是的,可以
以下代碼片段會經常出現在程序中,如果異常處理那麼重要,為什麼還會有這麼多開發人員一直這樣做呢?
try {
...
} catch (Exception e) {
e.printStackTrace();
}
經常出現的代碼並不代表是對的;
可能很多開發人員都使用eclipse的快速修復,自動生成異常處理代碼,如上所示,其實除了記錄下log,並沒有做什麼處理;
正如條目2所描述的,如果不能正確處理該異常的話,最好拋出異常,以便異常盡早被發現;
譯文鏈接:http://www.programcreek.com/2013/10/top-10-questions-about-java-exceptions/