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

2021-02-18 Java中文社群
前言

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

目錄檢查型異常(checked) vs. 非檢查型異常(Unchecked)為什麼在try代碼塊中聲明的變量不能在catch或者finally中被引用?為什麼 Double.parseDouble(null) 和 Integer.parseInt(null) 拋出的異常不一樣呢?try語句有return那麼finally還會執行嗎?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中經常使用的運行時異常

這裡列舉一部分:

IllegalArgumentExceptionArrayIndexOutOfBoundsException

在有些場景某個目標對象不滿足我們的預期,會用到這些異常,例如下面在 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();
}

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

參考文獻:Unchecked exceptions in JavaThe root of Java exception class hierarchyJava exceptions related questions in stackoverflow

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

相關焦點

  • 核桃乾貨 | 最常見的10種Java異常問題!
    LocalTime time = LocalTime.now();        System.out.println("獲取當前的時間,不含有日期:"+time);    }}通過增加小時、分、秒來計算將來的時間很常見。
  • Java認證:java運行時常見異常
    總結了幾個JAVA中常見的RuntimeException:  NullPointerException:空指針異常類  示例:  package com.darkmi.basic;  public class Test {  public static void
  • Java異常面試問題
    未經檢查的異常主要是由編程不良引起的,例如在對象引用上調用方法時的NullPointerException,而不確保它不為null。例如,我可以編寫一個方法來從字符串中刪除所有元音。確保不傳遞空字符串是調用者的責任。我可能會改變方法來處理這些場景,但理想情況下,調用者應該處理這個問題。Java中throw和throws關鍵字有什麼區別?
  • Java編程中常見的異常
    數組的初始化是對數組分配需要的空間,而初始化後的數組,其中的元素並沒有實例化,依然是空的,所以還需要對每個元素都進行初始化(如果要調用的話)2.java.lang.classnotfoundexception    這個異常是很多原本在jb等開發環境中開發的程式設計師,把jb下的程序包放在wtk下編譯經常出現的問題,異常的解釋是
  • Java異常的十大問題總結
    本文總結了有關Java異常的十大常見問題。1.已檢查與未檢查簡而言之,必須在方法中顯式捕獲已檢查的異常或在方法的throws子句中聲明該異常。未檢查的異常是由無法解決的問題引起的,例如被零除,空指針等。
  • Java常見異常及解釋
    常見 Java 異常解釋:(譯者註:非技術角度分析。
  • Java項目中常見的異常產生原因及處理辦法
    使用throw語句可以隨時拋出這種異常對象:throw new ArithmeticException(…);二、異常發生的原因有很多,通常包含以下幾大類:三、幾種常見的異常及其產生原因1、java.lang.NullPointerException(空指針異常)原因:這個異常大家肯定都經常遇到,異常的解釋是"程序遇上了空指針",即,調用了未經初始化的對象或者是不存在的對象
  • Java 最常見面試題
    4.final 在 java 中有什麼作用?5.java 中的 Math.round(-1.5) 等於多少?6.String 屬於基礎的數據類型嗎?7.java 中操作字符串都有哪些類?它們之間有什麼區別?8.String str="i"與 String str=new String(「i」)一樣嗎?
  • java NullPointerException異常處理
    java語言與其他程式語言不同,它有嚴格的異常處理機制,如果需要拋出異常的代碼塊中沒有捕獲異常,程序將不會成功編譯,換言之:未使用異常捕獲、異常捕獲方式不正確等,都將導致代碼不能被jvm編譯。java標準庫,內建了大量的異常處理類,這些類以Throwable 設計為最頂層類。
  • Java程式設計師必備:異常的十個關鍵知識點
    一. 異常是什麼異常是指阻止當前方法或作用域繼續執行的問題。比如你讀取的文件不存在,數組越界,進行除法時,除數為0等都會導致異常。<init>(FileInputStream.java:138) at java.io.FileInputStream.<init>(FileInputStream.java:93) at exception.TestException.main(TestException.java:10)二.
  • 常見的類加載異常
    上篇文章回顧了一下類加載的委派模型和類加載的三個階段所做的一些事情,本篇文章準備介紹一下 Java 程序運行中常見的類加載異常。
  • OutOfMemoryError異常的常見原因
    最常見的有這3種java.lang.OutOfMemoryError: Java heap spacejava.lang.OutOfMemoryError: PermGen spacejava.lang.OutOfMemoryError: GC overhead
  • Java基礎入門之異常、異常分類、異常防護解析
    在程序執行中,任何中斷正常程序運行就是異常。(二)java中引起異常因素第一種,Java 虛擬機檢測到不正常的運行,這些狀態可能是由以下幾種情況引起的:1.表達式算數異常,例如3被0整數。第二種,Java代碼中的throw 語句被運行。第三種,異步異常,這個異常可能的原因是1.thread 的stop 方法被執行。
  • 手把手教你定位常見Java性能問題
    概述性能優化一向是後端服務優化的重點,但是線上性能故障問題不是經常出現,或者受限於業務產品,根本就沒辦法出現性能問題,包括筆者自己遇到的性能問題也不多,所以為了提前儲備知識,當出現問題的時候不會手忙腳亂,我們本篇文章來模擬下常見的幾個Java性能故障,來學習怎麼去分析和定位。
  • 國外投資銀行最常問的10個Java面試問題!
    這篇來自國外的面試文章清楚表明很多Java開發人員樂於向花旗銀行、巴克萊銀行,瑞士信貸銀行提交申請,但很多人可能還不清楚面試時可能會被問到哪些問題。  本文的作者分享了投資銀行的一些常見面試問題,主要針對3年以上工作經驗的Java開發人員,這些問題不適用於新手或具有1 - 2年Java經驗的人員。通常情況下,銀行開放式訪談不會僱傭經驗較少的開發者。
  • Java最常見600+面試題全解析:面試必備
    尚學堂與500+企業合作,建立IT行業最全的企業面試題庫。每周8~20家企業上門招聘,輕鬆掌握企業最新面試題集。本題集幾乎都是【必考題】,都能看懂的話,保你面試十拿九穩。本題集由尚學堂學員整理,對應聘Java程式設計師職位的常見考點和知識體系都進行了分類和歸納整理。
  • JAVA異常及其異常處理方式
    比如說,你的代碼少了一個分號,那麼運行出來結果是提示是錯誤 java.lang.Error;如果你用System.out.println(100/0),那麼你是因為你用0做了除數,會拋出 java.lang.ArithmeticException 的異常。
  • Java 最常見的 200+ 面試題:面試必備
    適宜閱讀人群需要面試的初/中/高級 java 程式設計師想要查漏補缺的人想要不斷完善和擴充自己 java 技術棧的人java10.String 類的常用方法都有那些?11.抽象類必須要有抽象方法嗎?12.普通類和抽象類有哪些區別?
  • Java 中的異常和處理詳解
    javac在編譯時,不會提示和發現這樣的異常,不要求在程序處理這些異常。所以如果願意,我們可以編寫代碼處理(使用try…catch…finally)這樣的異常,也可以不處理。對於這些異常,我們應該修正代碼,而不是去通過異常處理器處理 。這樣的異常發生的原因多半是代碼寫的有問題。
  • [初級]Java開發人員最常犯的10個錯誤
    原因是忽略了一個關鍵的問題:當一個元素被刪除時,列表的大小縮小並且下標也會隨之變化,所以當你想要在一個循環中用下標刪除多個元素的時候,它並不會正常的生效。也有些人知道以上代碼的問題就由於數組下標變換引起的。