快要考试了,根据所给提纲和上课所学边复习边罗列一下重难点吧。学得不好,如有疏漏欢迎指正!
一、健壮性和正确性
健壮性:系统在不正常输入或不正常外部环境下仍能够表现正常的程度
原则:封闭实现细节,限定用户的恶意行为
考虑极端情况,没有“不可能”
正确性:程序按照spec加以执行的能力,是最重要的质量指标
测量:
外部观察角度:平均故障间隔时间(MTBF)
内部观察角度:残余缺陷率(软件发布后留下的bug)
对比:
正确性倾向于报错,健壮性则倾向于容错
对外的接口,倾向于健壮;对内的实现,倾向于正确
Reliability(可靠性) = Robustness + Correctness
Example:
二、Throwable
Throwable有两个子类,即error和exception
(1)error 内部错误:程序员通常无能为力,一旦发生,想办法让程序优雅的结束
种类:用户输入错误、设备错误、物理限制
大多数时候不需要实例化
(2)exception 异常:你自己程序导致的问题,可以捕获、可以处理
不应捕获程序自身的异常(除了自己测试)
程序执行中的非正常事件,程序无法再按预想的流程执行
Example:
三、Error/Runtime异常、其他异常
运行时异常:由程序员在代码里处理不当造成,如空指针、数组越界、类型转换等
——如果在代码中提前进行验证,这些故障就可以避免
其他异常:由外部原因造成
——即使在代码中提前加以验证(文件是否存在),也无法完全避免失效发生
四、Checked异常、Unchecked异常
异常被谁check?——编译器、程序员
Unchecked异常:Errors and Runtime Exceptions
Checked异常:else Exception,需要从Exception派生出子类型
注:尽量使用unchecked exception来处理编程错误:因为unchecked exception不用使客户端代码显式的处理它们,它们自己会在出现的地 方挂起程序并打印出异常信息。
如果client端对某种异常无能为力,可以把它转变 为一个unchecked exception,程序被挂起并返回 客户端异常信息
Checked exception应该让客户端从中得到丰富的信息。
要想让代码更加易读,倾向于用unchecked exception来处理程序中的错误
异常也是归约的一部分,必须明确写出所有checked exception
子类满足协变:不能更多,可以更具体也可以不抛
对比:
五、Checked异常的处理机制
- 抛出:声明是throws,抛出时throw
- 捕获(try/catch):try出现异常,忽略后面代码直接进入catch;无异常不进入catch;若catch中没有匹配的异常处理,程序退出;若子类重写了父类方法,父类方法没有抛出异常,子类应自己处理全部异常而不再传播;子类从父类继承的方法不能增加或更改异常
- 处理:不能代替简单的测试,尽量苛刻、不过分细化、将正常处理与异常处理分开、利用好层次结构、早抛出晚捕获、避免不必要的检查
- 清理现场、释放资源(finally):finally中语句不论有无异常都执行
六、自定义异常类
继承自Exception,包含更多“案发现场”信息、记录现场信息、为用户提供更有价值的帮助
七、断言的作用、应用场合
断言:在开发阶段的代码中嵌入,检验某些“假设”是否 成立。若成立,表明程序运行正常,否则表明存在错误。
作用:为了在开发阶段调试程序、尽快避免错误,主要用于开发阶段,避免引入 和帮助发现bug,实际运行阶段, 不再使用断言
应用场合:内部不变量、表示不变量、控制流不变量、方法的前置条件、方法的后置条件
注:断言 -> Correctness;错误/异常处理 -> Robustness
使用断言处理 “绝不应该发生”的情况
不管是否-ea, spec中的pre-/post-conditions都能够被保证
即使spec被违反,也不应通过assert直接fail,而是 应抛出具体的runtime异常
如果参数来 自于外部(不受自己控制),使用异常处理
开发阶段用断言尽可能消除bugs 在发行版本里用异常处理机制处理漏掉的错误
八、防御式编程的基本思路
(1)阻止非法输入:对来自外部的数 据源要仔细检查,例如:文件、网络数据、用户输入等;对每个函数的输入 参数合法性要做仔细检查,并决定如何处理非法输入
(2)设置路障:“隔离舱”外部的函数应使用异常处理,“隔离舱”内的函数应使用 断言