![Flutter从0基础到App上线](https://wfqqreader-1252317822.image.myqcloud.com/cover/259/33831259/b_33831259.jpg)
3.7 异常
在代码实际运行中,难免会出现一些问题导致程序发生错误甚至崩溃,我们称之为异常。在Dart中,也会抛出(即出现)异常和捕捉异常。如果异常未经补货,就很可能造成程序崩溃。
Dart编程语言提供了Exception和Error两类异常。除此之外,还有很多它们的子类,甚至还可以自定义异常类型,其中自定义的异常类型不能为空值。下面来看一看如何抛出异常,以及如何捕捉它们。
3.7.1 Throw
先来看一下如何抛出一个已知类型的异常:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_145.jpg?sign=1739346252-hNQNlotB9e6ogcIIDMQ88LUwHPZWF27v-0-142d5267ee89922ea9ccccf04d395d75)
运行代码,控制台将会出现报错提示:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_146.jpg?sign=1739346252-7XiE2MYn6LXBTmZj39bCP98Hxs6UcAXT-0-0ed27bc5471c7191b3d9089495153777)
一旦程序发生异常,就会终止运行,后面的逻辑将不会被执行。实际上,如果尝试在IDE中抛出异常的代码后面继续写代码的话,就会出现Dead Code警告。因为IDE检测到了抛出异常的代码,在此之后的代码就不会被执行,所以在此后面的代码均为Dead Code。
那么,如何自定义异常呢?同样非常简单,代码片段如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_147.jpg?sign=1739346252-76GMplYUFb2FSxuxXy1njZ2NmjwO4Hpf-0-63b9b995e0613789ae24069dd5459630)
运行代码,控制台依然会有报错提示:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_148.jpg?sign=1739346252-4Bbfb8UxQ3xm0DfUkEcmKZnb4d59gqaK-0-e8a78078f4544ac52c25d96be556a448)
从输出的结果上看,自定义的Custom exception已经得到体现。
当然,这样的自定义异常似乎是没有任何意义的,只能做讲解演示用。在实际生产环境中,自定义异常通常的做法是写一个类,声明Error或Exception类中的方法。这会涉及类、继承等知识,我们会在下一章讲解。
3.7.2 Catch
更多的时候,我们希望程序能够捕捉一些可能发生的异常情况,以避免程序崩溃。这就好像生活中我们打的预防针,因为身体提前有了抗体,所以就可以抵抗病毒了,而在Dart中是通过Catch来捕捉异常的。首先尝试运行如下代码:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_149.jpg?sign=1739346252-7TZaiRzClzkqsUdUgDvam6amnZOmXMpB-0-c42272bb8877851f5543b86c64f77607)
我们知道列表的下标是从0开始的,而上例中最后一个下标是4,但在print()方法中却取了5号下标,因此,程序会崩溃。运行结果如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_150.jpg?sign=1739346252-PXXzcNYcsw9SildoqNuZDBaE5JiZDxJt-0-965f0128f9bf8d4b76b1964860846196)
千万不要以为自己能够完全规避这类问题。当程序的逻辑愈加复杂时,开发者有可能真的会出现这样的问题。而问题一旦发生,程序就会崩溃,对于使用者就是一次非常不好的体验。
为了规避程序崩溃的风险,正确的做法实际上是将值改正确。但在这里为了讲解方便,故意不改这个错误的值,而是使用Catch来捕获这个异常并处理它。代码片段如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_151.jpg?sign=1739346252-ZSCkGbijozWb8l4uT9GrrHNpQDVBmfbJ-0-f159dec72a3355c3668550fe45fae1bc)
运行结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_152.jpg?sign=1739346252-3kg2J9VJmO3FcLzciAZDJqbYrJHbOsqc-0-a1963f810d9848ce562e4aa250c8fd7b)
在上面的代码中,首先使用一个try的代码块来包裹可能出现异常的代码,然后catch紧跟其后,e是包含异常信息的对象。处理的方法是将异常信息输出,然后按照正确的写法输出值,便得到了上面的运行结果。
在某些情况下,由于被try包裹起来的代码不一定只发生一种类型的异常,所以就需要分别对每一种异常进行处理。对于这种分情况进行处理的需求,只需要去捕捉不同的异常即可。代码如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_153.jpg?sign=1739346252-yoHxETm0WhYLJNioMi2K8zT2GcISEhai-0-c34962748fe6cb0127148c3a6774a01e)
运行结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_154.jpg?sign=1739346252-B8GIw0JjLwFwD93mnE0QfJuJa9HjvSge-0-5b7820aad58b5cc68123ffebcebb498e)
这一次并没有输出详细的错误信息,因为代码的逻辑走到了on RangeError分支,而输出详细的错误信息是作为默认异常处理才会被执行的。
在某些情况下,我们可能需要再次抛出异常,尽管这种情况很少见。其实再次抛出异常很简单,只需要在catch的代码块中使用rethrow即可。代码如下:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_155.jpg?sign=1739346252-FN3HQnoJdoNv8E6iDOuiJ5DvTne64T7G-0-d60186b4806f9ac9c36a9a9ce1e5c324)
运行结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_156.jpg?sign=1739346252-llxX9nAOButK2PmyRqxLSJ0RSOTCMwDe-0-c099fdd463fb9c8579188871593faaf2)
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_157.jpg?sign=1739346252-U24ehYEkW4xSoMy1pKkiZBVgbXTaEemf-0-ed6a1eb1c5f4d4d6a32e3e0bace53140)
3.7.3 Finally
当在运行完一些可能引起异常的代码逻辑后,仍需要执行一些语句完成后面的工作时,就需要使用finally代码块包裹后面的代码。具体参考如下示例:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_158.jpg?sign=1739346252-PEbIhVdhk3fz7uky13MB1XJ4ccXQGqfG-0-4bf3577f74e89325ad72cda9ea71d171)
运行结果:
![img](https://epubservercos.yuewen.com/9CF474/18096059801207706/epubprivate/OEBPS/Images/txt003_159.jpg?sign=1739346252-3beW1CkPTFvqJMQo2GI8vpc6SJ1j8p0h-0-cd5a2332c238e64fd1531830973bd1b4)
当然,这是没有抛出异常的情况。你可以自行尝试依然执行print(intArray[5]),观察在出现异常时的运行结果。