跳到主要內容

錯誤處理

異常

#

你的 Dart 程式碼可以丟擲和捕獲異常。異常是表示發生了意外情況的錯誤。如果異常未被捕獲,丟擲異常的隔離區 (isolate) 將被掛起,通常該隔離區及其程式也會終止。

與 Java 不同,Dart 的所有異常都是非檢查異常。方法不會宣告它們可能丟擲哪些異常,並且你無需捕獲任何異常。

Dart 提供了 ExceptionError 型別,以及許多預定義的子型別。當然,你可以定義自己的異常。然而,Dart 程式可以丟擲任何非空物件作為異常,而不僅僅是 Exception 和 Error 物件。

丟擲

#

這是一個丟擲(或引發)異常的例子

dart
throw FormatException('Expected at least 1 section');

你也可以丟擲任意物件

dart
throw 'Out of llamas!';

因為丟擲異常是一個表示式,所以你可以在 => 語句以及任何允許表示式的地方丟擲異常

dart
void distanceTo(Point other) => throw UnimplementedError();

捕獲

#

捕獲異常可以阻止異常傳播(除非你重新丟擲異常)。捕獲異常讓你有機會處理它

dart
try {
  breedMoreLlamas();
} on OutOfLlamasException {
  buyMoreLlamas();
}

要處理可能丟擲多種型別異常的程式碼,可以指定多個 catch 子句。第一個匹配丟擲物件型別的 catch 子句會處理該異常。如果 catch 子句沒有指定型別,該子句可以處理任何型別的丟擲物件

dart
try {
  breedMoreLlamas();
} on OutOfLlamasException {
  // A specific exception
  buyMoreLlamas();
} on Exception catch (e) {
  // Anything else that is an exception
  print('Unknown exception: $e');
} catch (e) {
  // No specified type, handles all
  print('Something really unknown: $e');
}

如前面的程式碼所示,你可以使用 oncatch,或兩者都用。當你需要指定異常型別時使用 on。當你的異常處理器需要異常物件時使用 catch

你可以為 catch() 指定一個或兩個引數。第一個是被丟擲的異常,第二個是堆疊跟蹤(一個 StackTrace 物件)。

dart
try {
  // ···
} on Exception catch (e) {
  print('Exception details:\n $e');
} catch (e, s) {
  print('Exception details:\n $e');
  print('Stack trace:\n $s');
}

要部分處理異常,同時允許其繼續傳播,請使用 rethrow 關鍵字。

dart
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}.');
  }
}

Finally

#

為了確保無論是否丟擲異常都執行某些程式碼,請使用 finally 子句。如果沒有 catch 子句匹配該異常,異常會在 finally 子句執行後傳播。

dart
try {
  breedMoreLlamas();
} finally {
  // Always clean up, even if an exception is thrown.
  cleanLlamaStalls();
}

finally 子句在任何匹配的 catch 子句之後執行

dart
try {
  breedMoreLlamas();
} catch (e) {
  print('Error: $e'); // Handle the exception first.
} finally {
  cleanLlamaStalls(); // Then clean up.
}

要了解更多資訊,請查閱核心庫異常文件

斷言

#

在開發期間,使用 assert 語句 — assert(<condition>, <optionalMessage>); — 如果布林條件為假,則中斷正常執行。

dart
// Make sure the variable has a non-null value.
assert(text != null);

// Make sure the value is less than 100.
assert(number < 100);

// Make sure this is an https URL.
assert(urlString.startsWith('https'));

要為斷言附加訊息,請將一個字串作為 assert 的第二個引數(可選地帶上尾隨逗號

dart
assert(
  urlString.startsWith('https'),
  'URL ($urlString) should start with "https".',
);

assert 的第一個引數可以是任何解析為布林值的表示式。如果表示式的值為 true,斷言成功並繼續執行。如果為 false,斷言失敗並丟擲異常(一個 AssertionError)。

斷言到底何時起作用?這取決於你使用的工具和框架

在生產程式碼中,斷言會被忽略,並且不會評估 assert 的引數。