Dart基础之异常

902 阅读3分钟

前言

一个成熟的计算机语言必须有异常机制。

为什么呢?

因为它可以帮助开发者们更好的发现bug和解决bug。

接下来我们来看下Dart的异常机制:

Dart代码是支持抛出和捕获异常的。异常通常是意外情况发生时的错误指示。

如果异常没有捕获,那么isolate会接管已经挂起异常,并且通常情况下isolate和它程序会被中止。

什么是 isolate ???

isolate 是 隔离区 的英文,如果很难理解,我们不妨把它理解成一个沙盒。

大多数计算机,即使在移动平台上,也有多核CPU。 为了利用所有这些核心,开发人员传统上使用并发运行的共享内存线程。 但是,共享状态并发容易出错,并且可能导致代码复杂化。

所有Dart代码都在隔离区运行,而不是线程。 每个隔离区都有自己的内存堆,确保不会从任何其他隔离区访问到自己隔离区的状态。

与Java相比,Dart的所有异常都是未经检查的异常。 方法不会声明它们可能引发的异常,并且你不需要捕获任何异常。

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

throw

下面是抛出或者挂起一个异常的例子:

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

你也可以抛出任意对象:

throw 'Out of llamas!';

注意:生产环境质量高的代码通常会抛出已经实现了的错误或异常的类型。

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

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

catch

捕获或捕捉异常会停止异常传递(除非你重新抛出异常)。 捕获异常让你有机会处理它:

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

要处理可能抛出多种类型异常的代码,可以指定多个catch子句。 与抛出对象的类型匹配的第一个catch子句处理异常。 如果catch子句未指定类型,则该子句可以处理任何类型的抛出对象:

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或两者。 需要指定异常类型时使用。 在异常处理程序需要异常对象时使用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++); // 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子句运行后传递异常:

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

finally子句在任何匹配的catch子句之后运行:

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