Java 異常處理機制中,finally 區塊的行為常讓開發者踩坑。本文針對兩大核心特殊情況進行深度解析,並附上程式碼驗證。
finally 區塊中執行 return、continue 等控制流語句,否則會「吞沒」異常。try 或 catch 區塊中有 return 語句,JVM 會在執行 return 前,先執行 finally 區塊。public class TryTest {
public static void main(String[] args) {
try {
System.out.println(TryTest.test()); // 輸出 true,異常被吞沒
} catch (Exception e) {
System.out.println("Exception from main");
e.printStackTrace();
}
doThings(0);
}
public static boolean test() throws Exception {
try {
throw new Exception("Something error"); // 步驟 1: 拋出異常
} catch (Exception e) { // 步驟 2: 捕獲異常
System.out.println("Exception from e"); // 步驟 3: 列印
return false; // 步驟 5: return 前控制權轉移至 finally,執行完畢後返回(但此步驟被吞沒,不執行)
} finally {
return true; // 步驟 4: 控制權轉移,直接返回,吞沒了異常
}
}
public static void doThings(int i) {
try {
if (i == 0) {
return; // 在執行 return 前會先執行 finally
}
int t = 100 / i;
System.out.println(t);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
System.out.println("finally");
}
}
}
test() 方法 —— 異常被「吃掉」try 區塊拋出 Exception。catch 區塊捕獲,列印訊息,遇到 return false。false 前,必須先執行 finally 區塊。finally 區塊執行 return true,直接終止方法並返回 true,導致 catch 區塊的 return false 被覆蓋,原始異常也隨之「消失」。main 接收到 true,catch 區塊永遠不會被觸發。結論: finally 中的 return 會強制覆蓋外層的返回值並吞沒異常,這是極度危險的反模式。
doThings(0) 方法 —— 正常流程下的 finally 執行順序if (i == 0) 條件成立,遇到 return。finally 區塊執行 System.out.println("finally")。finally 執行完畢後,方法才正式返回。輸出結果: finally
finally 中使用 return、throw、break、continue。finally 僅用於資源釋放(關閉流、釋放鎖、清理連線等)。catch 區塊設置標記變數,並在 try-catch-finally 結構外統一返回。理解 finally 的執行時機與優先級,是編寫健壯 Java 程式的必修課。