最常見的10種Java異常問題!

封面:洛小汐

者:潘潘

前言

本文總結了有關Java異常的十大常見問題。

目錄

  1. 檢查型異常(checked) vs. 非檢查型異常(Unchecked)
  2. 異常管理的最佳實踐箴言
  3. 爲什麼在try代碼塊中聲明的變量不能在catch或者finally中被引用?
  4. 爲什麼 Double.parseDouble(null) 和 Integer.parseInt(null) 拋出的異常不一樣呢?
  5. Java中經常使用的運行時異常
  6. 我們可以在同一個catch子句中捕獲多個異常嗎?
  7. 在 Java 中構造方法能拋出異常嗎?
  8. 在 final 代碼塊中拋出異常
  9. try語句有return那麼finally還會執行嗎?
  10. 爲何有些開發人員對異常置之不理?

1.檢查型異常(checked) vs 非檢查型異常(Unchecked)

簡單來說,對於檢查型異常, 一般在 編譯期 就會被檢查到,所以我們肯定會提前在方法內進行捕獲處理,或者在方法頭部申明並拋出。而非檢查型異常,往往無法提前預知,例如被除數是0、空指針等。檢查型異常特別重要,它會告訴那些調用你的接口的開發者們,如何提前預知並處理好這些可能發生的異常。

例如,IOException就是常見的檢查型異常,而 RuntimeException(運行時異常)就是非檢查型異常。在閱讀剩餘部分之前你或許可以研讀這份Java異常的層次結構圖。

2.異常管理的最佳實踐箴言

如果可以正確處理異常,則應將其捕獲並處理,否則應將其拋出。

3. 爲什麼在try代碼塊中聲明的變量不能在catch或者finally中被引用?

看下面這段代碼,在try代碼塊中聲明的 String 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代碼塊中哪個位置會引發異常, 很有可能在聲明對象之前就引發了異常。對於這個特定的示例,是正確的。

4.爲什麼 Double.parseDouble(null) 和 Integer.parseInt(null) 拋出的異常不一樣呢?

它倆拋出的異常確實不同,但這是JDK的問題,當時開發這兩個接口的開發人員不是同一波,所以我們沒必要去糾結這個問題。

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

Double.parseDouble(null); 
// throws java.lang.NullPointerException

5.Java中經常使用的運行時異常

這裏列舉一部分:

IllegalArgumentException ArrayIndexOutOfBoundsException

在有些場景某個目標對象不滿足我們的預期,會用到這些異常,例如下面在 if 判斷語句中被使用:

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

6.我們可以在同一個catch子句中捕獲多個異常嗎?

答案是當然可以,不過如果在同一個catch子句中捕獲的這些異常都直接或間接繼承自同一父類,那麼就只能在catch子句中捕獲父類了。

// Java 7 之前需要這樣
catch (AException a) {
     logger.error(a);
     throw new MyException("a");
catch (BException b) {
     logger.error(b);
     throw new MyException("b");
}catch (CException c) {
     logger.error(c);
     throw new MyException("c");
}

// 在Java 7中,可以捕獲所有這些異常 
catch(AException | BException | CException ex){
     logger.error(ex);
     throw new MyException(ex);
}

補充說明 : 其實是這樣,在 Java7 就開始支持catch子句捕獲多個異常,多個異常使用 XOR符號(I) 連接,異常的發生有可能是 A | B,但不能同時出現,相當於這些異常不能是間接或直接繼承自同一個父類,因爲如果AB都繼承同一父類,那就不能 A|B 都寫上,這也是繼承原則。

7.在 Java 中構造方法能拋出異常嗎?

答案是當然可以,構造方法僅是一種特殊方法而已。可以參考這個示例。

class FileReader{
 public FileInputStream fis = null;
 
 public FileReader() throws IOException{
  File dir = new File(".");//get current directory
  File fin = new File(dir.getCanonicalPath() + 
                          File.separator + "not-existing-file.txt");
  fis = new FileInputStream(fin);
 }
}

8.在 final 代碼塊中拋出異常

下面這個寫法是合法的:

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();
  }
 }
}

但是爲了獲得更好的代碼可讀性,你應該將把 try-catch代碼塊封裝成一個新方法,然後將方法調用放在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.try語句有return那麼finally還會執行嗎?

答案是肯定會執行。

Java官方文檔描述:The finally block always executes when the try block exits

意思就是 ” 只要存在try代碼塊,finally代碼塊就一定會執行 ” ,這種特性可以讓程序員避免在try語句中使用return, continue或者break關鍵字而忽略了關閉相關資源的操作等。

10.爲何有些開發人員對異常置之不理?

很多時候會見到下面這種代碼寫法。允許的情況下儘可能捕獲異常並且進行處理,不知道爲什麼很多開發人員就是這麼幹?

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

忽略異常是一件很容易做到的事,雖然這種寫法很常見,但不一定是正確的寫法。

參考文獻:
  1. Unchecked exceptions in Java
  2. The root of Java exception class hierarchy
  3. Java exceptions related questions in stackoverflow

譯文完,由於個人理解能力和知識寬度有限,譯文中存在失誤之處,還請見諒,歡迎指正。


   
   
   

往期推薦

SpringBoot接口冪等性實現的4種方案!


try-catch-finally中的4個巨坑,老程序員也搞不定!


對象複製的7種方法,還是Spring的最好用!


關注我,每天陪你進步一點點!

本文分享自微信公衆號 - Java中文社羣(javacn666)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章