第七章软件结构的健壮性——错误与异常处理
1. java中的异常与错误
这里如果读者对java语法有信心,那么大可跳过,因为主要说的是异常与错误的解释与区别,代码码的多了应该自然就懂了。
java中异常(Exception)和错误(Error)虽然导致都是程序出现GG的现象,但是有着本质的不同,形象点说你打一把DOTA,错误和异常都能中止你那行云流水的万分大神操作,但错误指的是你的鼠标爆炸键盘冒奶这种没有办法的现象,异常则指的是游戏中对面的敌人一套技能把你秒了。
具体概念:
- 错误(Error)是内部错误,程序员通常无能为力,一旦发生就想想办法怎么样程序优雅而不失逼格的结束。
- 异常(exception)则是你自己程序导致的问题,可以捕获、也可以处理。
(敌人现在把你秒了,但你可以一会出一把圣剑把他们全杀了,嘿嘿嘿)
这么说可能还是有点理解困难,举几个栗子吧:
错误,可以指用户输入错误、设备错误(无法连接服务器)、物理限制(内存不足)……
异常呢?那就好说多了,像什么空指针异常、数组越界异常,还有等等一系列自定义异常……总之我们都可以处理它!这一会我们都会详细说明。
2. 异常处理(Exception Handling)
嘛,就是catch……java学的很棒的读者可以跳过。
异常(Exception):
首先来给异常一个定义吧!
异常:程序执行中非正常的事件,程序无法再按照预想的流程执行。
异常会把错误信息逐级传递给上层调用者,并报告异常现场(栈),另外如果程序中找不到异常处理程序,整个系统会完全退出,这也是return之外的第二种退出途径。
异常分类:
异常可以分为两种:
- 运行时异常(RuntimeException):由程序员在代码中处理不当所致
- 其他异常:由外部原因造成
来个图:
在RuntimeException中,是程序源代码中引入的故障所致,如果在代码中提前验证就可以避免这些故障。
其他异常中,是程序员无法完全控制的外在问题所导致的,即使代码中提前加以验证(文件是否存在),也无法完全避免失效发生。
checked and unchecked exception:
这是从异常处理机制的角度出发,所做的另一种分类。
checked异常:编译器可以帮助你检查程序是否已抛出或处理了可能的异常。这里必须要捕获并制定错误处理器handler,否则编译无法通过!
unchecked异常:不需要编译的时候用try...catch等机制处理的异常。(Error + RuntimeException,注意RuntimeException的子类型也是),其可以不处理,编译会通过,但是执行时如果出现就会导致程序失败。
这两个有点类似静态检查和动态检查。
至于如何处理异常,try_catch_finally语句块,throws,与throw用法了解一下,这是java语法的内容,这里就不在赘余(很简单的,唉……告诉会Java的不用看,不会的又不说,什么人呐……)
这里有一点要说一下,unchecked异常也可以使用throws声明或者try_catch语句捕获,但是大多数是不需要的,也不应该这样做。(因为出现这个就意味着你的程序有问题辣!)
那么有个问题,我们什么时候采用checked异常,什么时候采用unchecked异常呢?
- checked异常:如果客户端可以通过其他方法恢复异常。
- unchecked异常:如果客户端对出现这种异常无能为力。
另外异常出现的时候,要做一些试图恢复他的动作,而不是仅仅打印他的信息。
在代码中,如果错误可预期无法预防,但有手段从中恢复时,采用checked异常,否则采用unchecked。另外我们也应该尽量采用unchecked异常来处理编程错误。而且不要创建没有意义的异常。总之checked异常应该让用户从中得到丰富的信息,如果想让代码边的更加易读,倾向于用unchecked异常来处理程序中的错误。
另外唠叨一句,如果有异常被抛出时,如果不想恢复它,就毫不犹豫的转换成unchecked异常,而不是用一个空catch块或者什么也不做。
来个对比图帮助理解:
3.异常的处理
嘛,这个就是java的语法基础了,毕竟也不是用博客说java语法的,而且相信大多数读者也都知道这些方法。所以这里就给方法了,至于如何使用度娘走你!另外了解java的读者也可以看一下是否有遗漏的方法。
分类:
- throws:这里唠叨一句,父类型与子类型要保证LSP原则的,不懂的读者可以翻一下我前面代码复用原则的内容哈。
- throw
- try_catch
- try_catch_finally:这里有一个比较有意思的题目,我放在后面大家可以看一哈。
- try-with-Resources
一颗赛艇的题目:
怎么样?结果是什么呢?敲进去试试,是不是有点不可思议呢?不得不说finally比return还nb!
answer:false