
Java 教程
- Java - 首頁
- Java - 概述
- Java - 歷史
- Java - 特性
- Java 與 C++
- JVM - Java 虛擬機器
- Java - JDK 與 JRE 與 JVM
- Java - Hello World 程式
- Java - 環境搭建
- Java - 基本語法
- Java - 變數型別
- Java - 資料型別
- Java - 型別轉換
- Java - Unicode 系統
- Java - 基本運算子
- Java - 註釋
- Java - 使用者輸入
- Java - 日期與時間
Java 控制語句
- Java - 迴圈控制
- Java - 決策制定
- Java - If-else
- Java - Switch
- Java - For 迴圈
- Java - For-Each 迴圈
- Java - While 迴圈
- Java - do-while 迴圈
- Java - Break
- Java - Continue
面向物件程式設計
- Java - OOPs 概念
- Java - 物件與類
- Java - 類屬性
- Java - 類方法
- Java - 方法
- Java - 變數作用域
- Java - 構造方法
- Java - 訪問修飾符
- Java - 繼承
- Java - 聚合
- Java - 多型
- Java - 重寫
- Java - 方法過載
- Java - 動態繫結
- Java - 靜態繫結
- Java - 例項初始化塊
- Java - 抽象
- Java - 封裝
- Java - 介面
- Java - 包
- Java - 內部類
- Java - 靜態類
- Java - 匿名類
- Java - 單例類
- Java - 包裝類
- Java - 列舉
- Java - 列舉構造方法
- Java - 列舉字串
Java 內建類
Java 檔案處理
Java 錯誤與異常
- Java - 異常
- Java - try-catch 塊
- Java - try-with-resources
- Java - 多重捕獲塊
- Java - 巢狀 try 塊
- Java - Finally 塊
- Java - throw 異常
- Java - 異常傳播
- Java - 內建異常
- Java - 自定義異常
Java 多執行緒
- Java - 多執行緒
- Java - 執行緒生命週期
- Java - 建立執行緒
- Java - 啟動執行緒
- Java - 執行緒連線
- Java - 執行緒命名
- Java - 執行緒排程器
- Java - 執行緒池
- Java - 主執行緒
- Java - 執行緒優先順序
- Java - 守護執行緒
- Java - 執行緒組
- Java - 關閉鉤子
Java 同步
Java 網路程式設計
- Java - 網路程式設計
- Java - 套接字程式設計
- Java - URL 處理
- Java - URL 類
- Java - URLConnection 類
- Java - HttpURLConnection 類
- Java - Socket 類
- Java - 泛型
Java 集合
Java 介面
Java 資料結構
Java 集合演算法
高階 Java
- Java - 命令列引數
- Java - Lambda 表示式
- Java - 傳送郵件
- Java - Applet 基礎
- Java - Javadoc 註釋
- Java - 自動裝箱和拆箱
- Java - 檔案不匹配方法
- Java - REPL (JShell)
- Java - 多版本 Jar 檔案
- Java - 私有介面方法
- Java - 內部類菱形運算子
- Java - 多解析度影像 API
- Java - 集合工廠方法
- Java - 模組系統
- Java - Nashorn JavaScript
- Java - Optional 類
- Java - 方法引用
- Java - 函式式介面
- Java - 預設方法
- Java - Base64 編碼解碼
- Java - Switch 表示式
- Java - Teeing 收集器
- Java - 微基準測試
- Java - 文字塊
- Java - 動態 CDS 歸檔
- Java - Z 垃圾收集器 (ZGC)
- Java - 空指標異常
- Java - 打包工具
- Java - 密封類
- Java - 記錄類
- Java - 隱藏類
- Java - 模式匹配
- Java - 緊湊數字格式化
- Java - 垃圾回收
- Java - JIT 編譯器
Java 雜項
- Java - 遞迴
- Java - 正則表示式
- Java - 序列化
- Java - 字串
- Java - 程序 API 改進
- Java - Stream API 改進
- Java - 增強的 @Deprecated 註解
- Java - CompletableFuture API 改進
- Java - 流
- Java - Datetime Api
- Java 8 - 新特性
- Java 9 - 新特性
- Java 10 - 新特性
- Java 11 - 新特性
- Java 12 - 新特性
- Java 13 - 新特性
- Java 14 - 新特性
- Java 15 - 新特性
- Java 16 - 新特性
Java API 和框架
Java 類參考
- Java - Scanner
- Java - 陣列
- Java - 字串
- Java - Date
- Java - ArrayList
- Java - Vector
- Java - Stack
- Java - PriorityQueue
- Java - LinkedList
- Java - ArrayDeque
- Java - HashMap
- Java - LinkedHashMap
- Java - WeakHashMap
- Java - EnumMap
- Java - TreeMap
- Java - IdentityHashMap
- Java - HashSet
- Java - EnumSet
- Java - LinkedHashSet
- Java - TreeSet
- Java - BitSet
- Java - Dictionary
- Java - Hashtable
- Java - Properties
- Java - Collection
- Java - Array
Java 有用資源
Java - 異常
什麼是 Java 中的異常?
異常(或異常事件)是在程式執行期間出現的問題。當異常發生時,程式的正常流程被打斷,程式/應用程式異常終止,這是不推薦的,因此,這些異常需要被處理。
為什麼發生異常?
異常可能由於多種原因發生。以下是發生異常的一些場景。
使用者輸入了無效資料。
需要開啟的檔案找不到。
網路連線在通訊過程中斷開或 JVM 記憶體不足。
其中一些異常是由使用者錯誤引起的,另一些是由程式設計師錯誤引起的,還有一些是由以某種方式發生故障的物理資源引起的。
Java 異常類別
基於此,我們有以下幾類異常。您需要了解它們才能知道 Java 中的異常處理是如何工作的。
- 受檢異常
- 非受檢異常
- 錯誤
Java 受檢異常
受檢異常是在編譯時由編譯器檢查(通知)的異常,這些異常也稱為編譯時異常。這些異常不能簡單地忽略,程式設計師應該注意(處理)這些異常。
示例:Java 中的受檢異常
例如,如果您在程式中使用FileReader類從檔案讀取資料,如果其建構函式中指定的檔案不存在,則會發生FileNotFoundException,編譯器會提示程式設計師處理該異常。
import java.io.File; import java.io.FileReader; public class FilenotFound_Demo { public static void main(String args[]) { File file = new File("E://file.txt"); FileReader fr = new FileReader(file); } }
如果您嘗試編譯上述程式,您將獲得以下異常。
輸出
C:\>javac FilenotFound_Demo.java FilenotFound_Demo.java:8: error: unreported exception FileNotFoundException; must be caught or declared to be thrown FileReader fr = new FileReader(file); ^ 1 error
注意 - 由於 FileReader 類的read()和close()方法丟擲 IOException,您可以觀察到編譯器會通知處理 IOException,以及 FileNotFoundException。
Java 非受檢異常
非受檢異常是在執行時發生的異常。這些異常也稱為執行時異常。這些包括程式設計錯誤,例如邏輯錯誤或 API 的不正確使用。執行時異常在編譯時被忽略。
示例:Java 中的非受檢異常
例如,如果您在程式中聲明瞭一個大小為 5 的陣列,並嘗試呼叫陣列的第 6 個元素,則會發生ArrayIndexOutOfBoundsException異常。
public class Unchecked_Demo { public static void main(String args[]) { int num[] = {1, 2, 3, 4}; System.out.println(num[5]); } }
如果您編譯並執行上述程式,您將獲得以下異常。
輸出
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 at Exceptions.Unchecked_Demo.main(Unchecked_Demo.java:8)
Java 錯誤
這些根本不是異常,而是超出使用者或程式設計師控制範圍的問題。在您的程式碼中通常會忽略錯誤,因為您很少能對錯誤做任何事情。例如,如果發生堆疊溢位,則會發生錯誤。它們在編譯時也被忽略。
Java 異常層次結構
所有異常類都是 java.lang.Exception 類的子型別。異常類是Throwable 類的子類。除了異常類之外,還有另一個稱為 Error 的子類,它派生自 Throwable 類。
錯誤是在發生嚴重故障時發生的異常情況,這些情況不會由 Java 程式處理。生成錯誤是為了指示執行時環境生成的錯誤。例如:JVM 記憶體不足。通常,程式無法從錯誤中恢復。
Exception 類有兩個主要的子類:IOException 類和 RuntimeException 類。

以下是Java內建異常中最常見的一些已檢查異常和未檢查異常的列表。Java的內建異常。
Java異常類方法
以下是Throwable類中一些重要方法的列表。
序號 | 方法及描述 |
---|---|
1 | public String getMessage() 返回關於發生的異常的詳細訊息。此訊息在Throwable建構函式中初始化。 |
2 | public Throwable getCause() 返回異常的原因,以Throwable物件表示。 |
3 | public String toString() 返回類的名稱與getMessage()結果的連線。 |
4 | public void printStackTrace() 將toString()的結果以及堆疊跟蹤列印到System.err(錯誤輸出流)。 |
5 | public StackTraceElement [] getStackTrace() 返回一個包含堆疊跟蹤中每個元素的陣列。索引為0的元素表示呼叫堆疊的頂部,陣列中的最後一個元素表示呼叫堆疊底部的呼叫方法。 |
6 | public Throwable fillInStackTrace() 用當前堆疊跟蹤填充此Throwable物件的堆疊跟蹤,並新增到堆疊跟蹤中的任何先前資訊。 |
捕獲異常:Java中的異常處理
方法使用try和catch關鍵字的組合來捕獲異常。try/catch塊放置在可能生成異常的程式碼周圍。try/catch塊中的程式碼稱為受保護程式碼,使用try/catch的語法如下所示:
語法
try { // Protected code } catch (ExceptionName e1) { // Catch block }
容易發生異常的程式碼放在try塊中。當發生異常時,發生的異常由與其關聯的catch塊處理。每個try塊都應該緊跟一個catch塊或finally塊。
catch語句涉及宣告您嘗試捕獲的異常型別。如果在受保護的程式碼中發生異常,則檢查try後面的catch塊(或塊)。如果發生的異常型別在catch塊中列出,則異常將傳遞到catch塊,就像引數傳遞到方法引數一樣。
示例:演示異常處理
在以下示例中,聲明瞭一個包含2個元素的陣列。然後程式碼嘗試訪問陣列的第3個元素,這將引發異常。
// File Name : ExcepTest.java import java.io.*; public class ExcepTest { public static void main(String args[]) { try { int a[] = new int[2]; System.out.println("Access element three :" + a[3]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Exception thrown :" + e); } System.out.println("Out of the block"); } }
輸出
Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3 Out of the block
多個Catch塊
try塊後面可以跟多個catch塊。多個catch塊的語法如下所示:
語法
try { // Protected code } catch (ExceptionType1 e1) { // Catch block } catch (ExceptionType2 e2) { // Catch block } catch (ExceptionType3 e3) { // Catch block }
前面的語句演示了三個catch塊,但在單個try之後可以有任意數量的catch塊。如果在受保護的程式碼中發生異常,則異常將拋到列表中的第一個catch塊。如果丟擲的異常的資料型別與ExceptionType1匹配,則會在那裡捕獲它。如果不是,則異常傳遞到第二個catch語句。這種情況將持續下去,直到異常被捕獲或貫穿所有catch,在這種情況下,當前方法將停止執行,並且異常將拋到呼叫堆疊上的前一個方法。
示例
以下程式碼段顯示瞭如何使用多個try/catch語句。
try { file = new FileInputStream(fileName); x = (byte) file.read(); } catch (IOException i) { i.printStackTrace(); return -1; } catch (FileNotFoundException f) // Not valid! { f.printStackTrace(); return -1; }
捕獲多種型別的異常
從Java 7開始,您可以使用單個catch塊處理多個異常,此功能簡化了程式碼。以下是如何執行此操作:
catch (IOException|FileNotFoundException ex) { logger.log(ex); throw ex;
Throws/Throw關鍵字
如果方法不處理已檢查異常,則該方法必須使用throws關鍵字宣告它。throws關鍵字出現在方法簽名末尾。
您可以使用throw關鍵字丟擲異常,無論是新例項化的異常還是剛剛捕獲的異常。
嘗試理解throws和throw關鍵字之間的區別,throws用於推遲已檢查異常的處理,而throw用於顯式呼叫異常。
以下方法宣告它丟擲一個RemoteException:
示例
import java.io.*; public class className { public void deposit(double amount) throws RemoteException { // Method implementation throw new RemoteException(); } // Remainder of class definition }
方法可以宣告它丟擲多個異常,在這種情況下,異常以逗號分隔的列表形式宣告。例如,以下方法宣告它丟擲一個RemoteException和一個InsufficientFundsException:
示例
import java.io.*; public class className { public void withdraw(double amount) throws RemoteException, InsufficientFundsException { // Method implementation } // Remainder of class definition }
Finally塊
finally塊位於try塊或catch塊之後。無論是否發生異常,finally塊中的程式碼始終都會執行。
使用finally塊,您可以執行任何您希望執行的清理型別語句,無論受保護程式碼中發生了什麼。
finally塊出現在catch塊的末尾,並且具有以下語法:
語法
try { // Protected code } catch (ExceptionType1 e1) { // Catch block } catch (ExceptionType2 e2) { // Catch block } catch (ExceptionType3 e3) { // Catch block }finally { // The finally block always executes. }
示例
public class ExcepTest { public static void main(String args[]) { int a[] = new int[2]; try { System.out.println("Access element three :" + a[3]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Exception thrown :" + e); }finally { a[0] = 6; System.out.println("First element value: " + a[0]); System.out.println("The finally statement is executed"); } } }
輸出
Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3 First element value: 6 The finally statement is executed
請注意以下幾點:
catch子句不能獨立存在,必須與try語句一起使用。
在存在try/catch塊時,不一定需要finally子句。
try塊不能獨立存在,必須與catch子句或finally子句一起使用。
try、catch、finally塊之間不能存在任何程式碼。
Try-with-resources
通常,當我們使用任何資源(如流、連線等)時,我們必須使用finally塊顯式關閉它們。在下面的程式中,我們使用FileReader從檔案中讀取資料,並使用finally塊關閉它。
示例
import java.io.File; import java.io.FileReader; import java.io.IOException; public class ReadData_Demo { public static void main(String args[]) { FileReader fr = null; try { File file = new File("file.txt"); fr = new FileReader(file); char [] a = new char[50]; fr.read(a); // reads the content to the array for(char c : a) System.out.print(c); // prints the characters one by one } catch (IOException e) { e.printStackTrace(); }finally { try { fr.close(); } catch (IOException ex) { ex.printStackTrace(); } } } }
try-with-resources,也稱為自動資源管理,是Java 7中引入的一種新的異常處理機制,它會自動關閉try catch塊中使用的資源。
要使用此語句,您只需在括號內宣告所需的資源,並且建立的資源將在塊結束時自動關閉。以下是try-with-resources語句的語法。
語法
try(FileReader fr = new FileReader("file path")) { // use the resource } catch () { // body of catch } }
以下是使用try-with-resources語句讀取檔案中的資料的程式。
示例
import java.io.FileReader; import java.io.IOException; public class Try_withDemo { public static void main(String args[]) { try(FileReader fr = new FileReader("E://file.txt")) { char [] a = new char[50]; fr.read(a); // reads the contentto the array for(char c : a) System.out.print(c); // prints the characters one by one } catch (IOException e) { e.printStackTrace(); } } }
在使用try-with-resources語句時,需要注意以下幾點。
要將類與try-with-resources語句一起使用,它必須實現AutoCloseable介面,並且它的close()方法會在執行時自動呼叫。
您可以在try-with-resources語句中宣告多個類。
當您在try-with-resources語句的try塊中宣告多個類時,這些類將按相反的順序關閉。
除了在括號內宣告資源之外,其他所有內容都與try塊的普通try/catch塊相同。
try中宣告的資源在try塊開始之前立即例項化。
在try塊中宣告的資源隱式宣告為final。
Java中的使用者定義異常
您可以在Java中建立自己的異常。在編寫自己的異常類時,請牢記以下幾點:
所有異常都必須是Throwable的子類。
如果您想編寫由Handle or Declare Rule自動執行的已檢查異常,則需要擴充套件Exception類。
如果您想編寫執行時異常,則需要擴充套件RuntimeException類。
語法
我們可以如下定義自己的異常類:
class MyException extends Exception { }
您只需要擴充套件預定義的Exception類即可建立自己的異常。這些被認為是已檢查異常。以下InsufficientFundsException類是一個使用者定義的異常,它擴充套件了Exception類,使其成為已檢查異常。異常類與任何其他類一樣,包含有用的欄位和方法。
示例:建立使用者定義異常
// File Name InsufficientFundsException.java import java.io.*; public class InsufficientFundsException extends Exception { private double amount; public InsufficientFundsException(double amount) { this.amount = amount; } public double getAmount() { return amount; } }
為了演示如何使用我們使用者定義的異常,以下CheckingAccount類包含一個丟擲InsufficientFundsException的withdraw()方法。
// File Name CheckingAccount.java import java.io.*; public class CheckingAccount { private double balance; private int number; public CheckingAccount(int number) { this.number = number; } public void deposit(double amount) { balance += amount; } public void withdraw(double amount) throws InsufficientFundsException { if(amount <= balance) { balance -= amount; }else { double needs = amount - balance; throw new InsufficientFundsException(needs); } } public double getBalance() { return balance; } public int getNumber() { return number; } }
以下BankDemo程式演示了呼叫CheckingAccount的deposit()和withdraw()方法。
// File Name BankDemo.java public class BankDemo { public static void main(String [] args) { CheckingAccount c = new CheckingAccount(101); System.out.println("Depositing $500..."); c.deposit(500.00); try { System.out.println("\nWithdrawing $100..."); c.withdraw(100.00); System.out.println("\nWithdrawing $600..."); c.withdraw(600.00); } catch (InsufficientFundsException e) { System.out.println("Sorry, but you are short $" + e.getAmount()); e.printStackTrace(); } } }
編譯上述三個檔案並執行BankDemo。這將產生以下結果:
輸出
Depositing $500... Withdrawing $100... Withdrawing $600... Sorry, but you are short $200.0 InsufficientFundsException at CheckingAccount.withdraw(CheckingAccount.java:25) at BankDemo.main(BankDemo.java:13)
常見的Java異常
在Java中,可以定義兩類異常和錯誤。
JVM異常 - 這些是JVM專門或邏輯上丟擲的異常/錯誤。例如:NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException。
程式異常 - 這些異常由應用程式或API程式設計師顯式丟擲。例如:IllegalArgumentException、IllegalStateException。