天天看点

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

面向正确性与健壮性的软件构造

  • 两个特性
    • 健壮性
    • 正确性
  • 错误与异常
    • Error
    • Exception
      • checked Exception
      • try-catch-finally
      • unchecked Exception
      • 自定义异常类
  • Assertions

两个特性

健壮性

1.健壮性:系统在不正常输入或不正常外部环境下仍能够表现正常的程度。

2.面向健壮性的编程

(1)处理未期望的行为和错误终止

(2)即使终止执行,也要准确/无歧义的向用户展示全面的错误信息

(3)错误信息有助于进行debug

尽可能保持软件运行而不是总是退出两者的比较

正确性

正确性:程序按照spec 加以执行的能力,是最重要的质量指标!

永不给用户错误的结果

两者的对比:

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions
软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

错误与异常

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

Error

1.Error类描述了Java运行时系统内部很少发生的内部系统错误和资源耗尽情况(例如,VirtualMachineError, LinkageError)。

不应该抛出这种类型的对象,如果发生这样的内部错误,除了通知用户并试图优雅地终止程序外,你能做的很少。

内部错误:程序员通常无能为力,一旦发生,想办法让程序优雅的结束

2.种类

(1)User input errors 用户输入错误

(2)Device errors 设备错误

(3)Physical limitations 物理限制

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

Exception

一.Exception类描述了由你的程序引起的错误(例如FileNotFoundException, IOException)。这些错误可以被你的程序捕获和处理(例如,执行一个替代操作或做一个优雅的退出关闭所有的文件,网络和数据库连接)。

异常:你自己程序导致的问题,可以捕获、可以处理

二.分类:

1.运行时异常:由程序员在代码里处理不当造成

2.其他异常:由外部原因造成

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

checked Exception

1.处理方法:

(1)你必须捕获和处理异常,或者告诉编译器不能处理它宣称你的方法抛出的异常,代码。

(2)然后使用你的方法将不得不处理,异常(可以选择声明抛出的异常,如果它不能处理)。

(3)编译器将检查我们是否完成了以下两件事中的一件(catch或declare)。

2.编译过程:

必须捕获并指定错误处理器handler,否则编译无法通过,类似于编程语言中的static type checking

从Exception中派生出子类型

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

编译器可帮助检查你的程序是否已抛出或处理了可能的异常

3.解决办法:

(1)Declaring exceptions (throws) 声明“本方法可能会发生XX异常”

(2)Throwing an exception (throw) 抛出XX异常

(3)Catching an exception (try, catch, finally) 捕获并处理XX异常

4.通过throws

在函数头后和spec中均声明异常的种类

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

父子函数–参见LSP原则

(1)如果子类型中override了父类型中的函数,那么子类型中方法抛出的异常不能比父类型抛出的异常类型更宽泛

(2)子类型方法可以抛出更具体的异常,也可以不抛出任何异常

(3)如果父类型的方法未抛出异常,那么子类型的方法也不能抛出异常。

错误示例:

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

5.通过throw

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

(1)找到一个能表达错误的Exception类/或者构造一个新的Exception类

(2)构造Exception类的实例,将错误信息写入,抛出它

一旦抛出异常,方法不会再将控制权返回给调用它的client,因此也无需考虑返回错误代码

6.通过try/catch

异常发生后,如果找不到处理器,就终止执行程序,在控制台打印出stack trace,所以可以通过try/catch捕获并处理异常

举例来看:

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

7.通过finally

(1)当异常抛出时,方法中正常执行的代码被终止,如果异常发生前曾申请过某些资源,那么异常发生后这些资源要被恰当的清理,可以使用finally进行处理

(2)可以不使用catch子句而使用finally子句。

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

不管代码是否抛出异常,finally都会被执行

try-catch-finally

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

分情况讨论:

1.该代码不抛出任何异常。

程序首先执行try块中的所有代码。然后执行finally子句中的代码。然后,执行finally子句后的第一个语句。换句话说,执行通过点1、2、5和6。

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

2.代码抛出一个异常,该异常在catch子句中被捕获。

程序执行try块中的所有代码,直到抛出异常为止。try块中的其余代码将被跳过。然后,程序执行匹配的catch子句中的代码,然后执行finally子句中的代码。

如果catch子句没有抛出异常,则程序执行finally子句后的第一行。执行通过点1、3、4、5和6。如果catch子句抛出一个异常,那么该异常将被抛回调用者,执行只通过点1、3和5。

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

3.该代码抛出一个未在任何catch子句中捕获的异常。

在这里,程序执行try块中的所有代码,直到抛出异常。跳过try块中的剩余代码。然后,执行finally子句中的代码,并将异常抛回给该方法的调用者。执行只通过点1和点5。

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

unchecked Exception

Errors and Runtime Exceptions

1.处理方法:

(1)错误表示发生在应用程序之外的情况,例如系统崩溃。运行时异常通常是由于应用程序逻辑中的错误而发生的。

(2)在这些情况下你什么都做不了,只能重写你的程序代码。所以编译器不会检查这些。

(3)这些运行时异常将在开发和测试期间发现。然后我们必须重构我们的代码来删除这些错误。

2.编译过程:

可以不处理,编译没问题,但执行时出现就导致程序失败,代表程序中的潜在bug类似于编程语言中的dynamic type checking

从RuntimeException 派生出子类型

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

3.举例:在编程和编译的时候,IDE与编译器均不会给出任何错误提示

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

两者比较

1.使用情况:

(1)如果客户端可以通过其他的方法恢复异常,那么采用checked exception;

(2)如果客户端对出现的这种异常无能为力,那么采用unchecked exception;

(3)异常出现的时候,要做一些试图恢复它的动作而不要仅仅的打印它的信息。

2.对比表格

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

自定义异常类

为了定义checked Exception,你要创建java.lang.Exception的一个子类(或子类的层次结构):

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

可能抛出或传播此异常的方法必须声明它:

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

举个例子:

软件构造笔记(十六)---PPT第十二讲两个特性错误与异常Assertions

Assertions

一.定义:在开发阶段的代码中嵌入,检验某些“假设”是否成立。若成立,表明程序运行正常,否则表明存在错误。

当断言为真时,意味着一切都按预期运行。

当断言为假时,意味着它在代码中检测到一个意外错误。