[Dart] 錯誤處理
錯誤處理
Dart 提供了兩個主要的異常類型:
Exception:表示程序中的邏輯錯誤或其他可預期的問題。開發者可以使用這個類型來表示可以處理或恢復的錯誤。Error:表示程序中的嚴重問題,通常是程序無法恢復的錯誤,如內存溢出、無效的狀態等。 或是開發者也可以自定義異常來更靈活處理錯誤。
資訊
錯誤處理在各種程式語言都很重要!
- 管理錯誤狀態:通過捕獲異常,開發者可以根據具體情況做出相應的處理,如提示用戶、重試操作、記錄日誌等。
- 避免程式碼中斷執行:通過適當的異常處理,可以防止程序因未處理的異常而崩潰,從而提高程序的健壯性和穩定性。
Catch 捕獲異常
Dart 捕獲異常是使用 try 配合 on 跟 catch:
try {
breedMoreLlamas();
} on OutOfLlamasException {
buyMoreLlamas();
}
也可以使用多個 catch 來處理不同類型的異常:
try {
breedMoreLlamas();
} on OutOfLlamasException {
// 處理特定的 OutOfLlamasException 異常
buyMoreLlamas();
} on Exception catch (e) {
// 處理所有其他的 Exception 類型的異常
print('Unknown exception: $e');
} catch (e) {
// 處理所有其他未被捕獲的異常
print('Something really unknown: $e');
}
資訊
on 跟 catch 的差異
on:用於處理特定類型的異常。適合需要區分不同異常類型並進行相應處理的情況。catch:用於捕獲所有異常,並可以獲取異常對象和堆棧跟蹤 (Stack Trace)。適合處理通用異常和需要詳細異常信息的情況。 從概念尚可以知道on跟catch負責的事情類似但本質不一樣:on就像售票員檢查入場券一樣,只讓有有效入場券的人進入。這意味著當特定類型的異常發生時,相應的處理程序將被觸發。catch就像救護人員在事故現場一樣。無論異常的類型是什麼,catch都會將它捕獲並進行相應的處理,無需對異常進行額外的分類。
Throw 拋出異常
以下是拋出異常的範例:
// example1
throw FormatException('Expected at least 1 section');
// example2
throw 'Out of llamas!';
// example3
void distanceTo(Point other) => throw UnimplementedError();
也可以透過 rethrow 在異常處理過程中重新抛出異常,以便讓上層調用者能夠感知和處理這個異常:
void misbehave() {
try {
dynamic foo = true;
print(foo++); // Runtime error
} catch (e) {
print('misbehave() partially handled ${e.runtimeType}.');
rethrow; // Allow callers to see the exception.
}
}
void main() {
try {
misbehave();
} catch (e) {
print('main() finished handling ${e.runtimeType}.');
}
}
解釋一下上面 rethrow 做了什麼:
misbehave()函式開始執行。- 在
misbehave()函式中,嘗試對一個 bool 變數進行自增操作,這是不合法的。 - 由於自增操作不合法,導致運行時錯誤。
- 運行時錯誤被
catch塊捕獲,程式執行進入catch塊。 - 在
catch塊中,打印一條消息,表明misbehave()函式部分處理了這個異常。 - 在
catch塊中,使用rethrow關鍵字重新抛出這個異常。 - 異常被重新抛出後,它會繼續向上傳播到
main()函式。 - 異常被
main()函式中的catch塊捕獲。 - 在
main()函式的catch塊中,打印一條消息,表明main()函式處理了這個異常。
Finally
finally 用於確保某些程式碼無論異常是否被拋出都會執行。
這意味著即使在 try 區塊中的程式碼引發異常,finally 中的程式碼仍然會被執行。
如果沒有 catch 子句去捕獲異常,則 finally 執行完畢後,該異常會繼續向外傳遞。
try {
breedMoreLlamas();
} finally {
// Always clean up, even if an exception is thrown.
cleanLlamaStalls();
}