你的dart代码可以抛出和捕获异常。异常指一些出乎意料的事情发生了。通常如果一个异常未被捕获时回终止程序或者当前的isolate(类似类似线程的东西)
与Java相反,所有的dart异常都是未受检异常。也就是说当调用一个可以抛出异常的方法时,不必一定去捕获这个异常。这点和Kotlin一样,都是为了简化代码,增加可读性。如果你担心这段代码真的会产生什么异常,那么可以自行捕获。
Dart提供了Exception
和Error
两种类型,并且提供了许多预定义的子类。当然你也可以定义自己的异常。然而Dart程序允许你将任何非空对象当作异常抛出,而非只有Exception和Error才能抛出。
Throw
这是一个抛出的用例:
throw FormatException('Expected at least 1 section');
你也可以抛出一个随意的对象:
throw 'Out of llamas!';
注意:产品质量的代码通常抛出实现了Exception和Error的异常。
throw
其实是表达式,他可以出现在表达式出现的任何地方:
void distanceTo(Point other) => throw UnimplementedError();
或者是这样:
person?.run()??throw 'person is null';
catch
catch
用来捕获异常,这和通常的语言语义相通。
try {
breedMoreLlamas();
} on OutOfLlamasException {
buyMoreLlamas();
}
捕获多种异常时如果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');
}
前面代码我们看到捕获异常可以用on
或者catch
或者两者都用,on
可以明确指定你要捕获的异常类型,catch
则可以使用异常对象。
catch还有第二个参数,他表示堆栈跟踪:
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.
}
更多关于异常的信息参考dart库部分的Exception