异常

优质
小牛编辑
141浏览
2023-12-01

你的 Dart 代码可以抛出和捕获异常。异常是指发生了未意料的错误。如果异常没被捕获,抛出异常的 isolate 会被挂起,一般情况下这会导致 isolate 和 应用程序终止。

与 Java 相反,Dart 中所有的异常都是未检查异常。方法不声明它们可能会抛出的异常,而且你没有被要求捕获任何异常。

Dart 提供了 ExceptionError 类型,以及众多预定义的子类。当然,你可以定义自己的异常。然而,Dart 程序可以抛出任何非空的对象——而不仅仅是 Exception 和 Error 对象——作为异常。

Throw

下面是抛出一个异常的例子:

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

你也可以抛出任意对象:

throw 'Out of llamas!';

说明:符合生产质量的代码通常抛出实现了 ErrorException 的类型。

因为抛出异常是一个表达式,你可以在 => 语句中抛出异常,以及任何允许表达式的地方抛出异常:

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

Catch

捕获异常会中止异常的传播(除非你又重新抛出这个异常)。捕获异常给了你处理它的机会:

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

要处理抛出超过一种类型异常的代码,你可以指定多个 catch 子句。第一个匹配抛出对象类型的子句处理这个异常。如果 catch 子句没有指定类型,那么这个子句可以处理任意类型的抛出对象:

try {
  breedMoreLlamas();
} on OutOfLlamasException {
  // 一个指定的异常
  buyMoreLlamas();
} on Exception catch (e) {
  // 任何是异常的对象
  print('Unknown exception: $e');
} catch (e) {
  // 未指定类型,处理所有对象
  print('Something really unknown: $e');
}

如前面代码所示,你可以使用 oncatch 或两者同时使用。当你需要指定类型时使用 on。当你的异常处理需要异常对象时使用 catch

你可以为 catch() 指定一个或两个参数。第一个参数是被抛出的对象,第二个是调用栈(一个 StackTrace 对象)。

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

要部分处理一个异常,而允许它继续传播,使用 rethrow 关键词。

void misbehave() {
  try {
    dynamic foo = true;
    print(foo++); // 运行期异常
  } catch (e) {
    print('misbehave() partially handled ${e.runtimeType}.');
    rethrow; // 允许调用者看到这个异常
  }
}

void main() {
  try {
    misbehave();
  } catch (e) {
    print('main() finished handling ${e.runtimeType}.');
  }
}

Finally

要确保一些代码无论是否有异常抛出都会执行,使用 finally 子句。如果没有 catch 子句匹配异常,异常在 finally 子句执行后继续传播:

try {
  breedMoreLlamas();
} finally {
  // 总是执行清理,即使有异常抛出
  cleanLlamaStalls();
}

Finally 子句在任意匹配的 catch 子句后执行:

try {
  breedMoreLlamas();
} catch (e) {
  print('Error: $e'); // 先处理异常
} finally {
  cleanLlamaStalls(); // 然后执行清理
}

阅读库教程中的 Exceptions 章节来了解更多内容。