CodeGym /課程 /JAVA 25 SELF /拋出例外(throws)

拋出例外(throws)

JAVA 25 SELF
等級 11 , 課堂 4
開放

1. 前言

在程式設計中,常常會遇到這樣的情況:方法碰到錯誤,但不知道該如何正確處理。例如,方法要讀取檔案,但不清楚當檔案不存在時該怎麼辦:詢問使用者?結束程式?改讀別的檔案?在這種情況下,方法可以「轉交責任」給呼叫者——也就是把例外「往上拋」到呼叫鏈的下一層。

拋出例外是一種機制,允許方法不必自行處理錯誤,而是告訴呼叫端:「我這裡出了問題,請你自己決定怎麼解決!」

類比:想像你是客服中心人員。客戶打來詢問一個你不知道答案的問題。與其胡亂猜測,你會說:「請稍候,我幫您轉接專家。」你就是把問題「往上轉交」。

關鍵字 throws:如何運作

在 Java 中,拋出例外是透過在方法宣告中使用關鍵字 throws 來完成。

語法:

tip_vozvrashchaemogo_znacheniya imyaMetoda(...) throws ExceptionType 
{
    // 方法的程式碼
}

throws 後面要註明此方法可能拋出的例外型別。這就像是對其他開發者的警示:「注意!這個方法可能會拋出某種型別的例外,請做好準備!」

範例:

public void readFile(String filename) throws FileNotFoundException 
{
    FileReader reader = new FileReader(filename); // 可能會拋出 FileNotFoundException
    // ...
}

這裡,readFile 方法不自行處理錯誤,而是宣告:「我可能會拋出 FileNotFoundException——讓呼叫我的人自己決定怎麼辦。」

2. 呼叫端應該如何因應?

如果你要呼叫一個在宣告中有 throws 的方法,你有兩種選擇:

  • try-catch 處理例外
  • 也把例外再往上拋(在自己的方法上加上 throws

作法一:用 try-catch 處理

public static void main(String[] args) 
{
    try 
    {
        readFile("data.txt");
    } 
    catch (FileNotFoundException e) 
    {
        System.out.println("找不到檔案:" + e.getMessage());
    }
}

在這裡我們捕捉例外並自行決定該怎麼做(例如向使用者輸出訊息)。

作法二:往上拋出

public static void main(String[] args) throws FileNotFoundException 
{
    readFile("data.txt");
}

現在,處理錯誤的責任就落在呼叫 main 的一方(通常是 JVM;如果錯誤未被處理,程式將會以錯誤訊息結束)。

3. 範例:帶有拋出例外的檔案讀取

包含 IOException 並在 main 層級處理的完整範例:

import java.io.*;

public class FileDemo 
{
    // 方法宣告自己可能拋出 IOException
    public static void printFirstLine(String filename) throws IOException 
    {
        BufferedReader reader = new BufferedReader(new FileReader(filename));
        String line = reader.readLine();
        System.out.println("第一行:" + line);
        reader.close();
    }

    public static void main(String[] args) 
    {
        try 
        {
            printFirstLine("nofile.txt");
        } 
        catch (IOException e) 
        {
            System.out.println("讀取檔案時發生錯誤:" + e.getMessage());
        }
    }
}

方法 printFirstLine 不知道在檔案不存在時該怎麼辦——它只是把例外往上拋。在 main 中我們捕捉錯誤並輸出訊息。

4. 實用細節

何時以及為什麼要拋出例外?

  • 當方法無法或不應決定如何處理錯誤(例如函式庫程式碼)。
  • 當錯誤處理取決於情境(有時結束程式,有時改讀別的檔案)。
  • 為了避免在不需要的地方以過多的 try-catch 使程式碼變得雜亂。

Best practice: 當你無法有意義地處理錯誤時,就把例外拋出。不要只為了「走流程」而捕捉例外!

可以拋出多種例外

public void process() throws IOException, SQLException 
{
    // ...
}

Checked 與 unchecked 例外:複習

Checked exceptions(例如 IOExceptionSQLException)——編譯器要求你要么處理它們、要么拋出它們。

Unchecked exceptions(例如 NullPointerExceptionIllegalArgumentException)——編譯器不要求處理,不需要在 throws 中列出。

5. 拋出例外時的常見錯誤

錯誤 1:忘記為 throws 宣告 checked 例外。
如果方法可能拋出 checked 例外,但你沒有在 throws 中宣告、也沒有用 try-catch 處理——編譯器會報錯。

錯誤 2:捕捉了例外卻不處理。
catch (Exception e) {} 是不良實務!如果不知道該怎麼處理,寧可把例外再往上拋。

錯誤 3:拋出過於寬泛的型別。
如果方法只可能拋出 FileNotFoundException,就不要寫 throws Exception——這會讓程式碼更難理解。

錯誤 4:在 throws 中列出 unchecked 例外。
throws NullPointerException 沒有意義——編譯器不要求,而且對錯誤處理沒有幫助。

1
任務
JAVA 25 SELF, 等級 11, 課堂 4
上鎖
機密文件存取模組 📁
機密文件存取模組 📁
1
任務
JAVA 25 SELF, 等級 11, 課堂 4
上鎖
日誌分析工具:處理讀取錯誤 📊
日誌分析工具:處理讀取錯誤 📊
1
任務
JAVA 25 SELF, 等級 11, 課堂 4
上鎖
資料處理管線:檔案可能遇到的問題 ⚙️
資料處理管線:檔案可能遇到的問題 ⚙️
1
任務
JAVA 25 SELF, 等級 11, 課堂 4
上鎖
淘金熱:轉換玩家輸入 💰
淘金熱:轉換玩家輸入 💰
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION