-
什么是异常?
影响程序正常运行的错误。 -
程序设计错误的分类:
编译错误(语法错误,由编译器查错)、运行时错误(数组下标越界、除零等,由异常处理)、逻辑错误(不满足设计要求,由人查错)。 -
异常发生难以避免:
程序设计理念不成熟、程序测试方法不完备(完备测试近乎无法实现)、用户软硬件环境导致。 -
设计时采用两种策略:
限制异常发生、为各种可能准备各类处理预案(即异常处理机制)
异常处理机制
- 传统异常处理手段: Error代码+goto语句
优点:简单易行,缺点:代码复杂、可读性差、识别不准确 - java异常处理策略: 将各种错误统一封装成异常对象,对异常对象处理或声明
java异常处理机制
捕获异常:try-catch-finally子句直接捕获
public void 上课(){
try{...上课过程相关语句...}//正常代码
catch(学生生病 e){...对学生生病的处理...}
catch(学生上厕所 e){...对学生上厕所的处理...}
finally{...确保上课质量...}
}
注:1、catch子句匹配顺序为排列顺序,子类异常必须排在超类之前;
2、try块一旦发生异常就跳转到对应catch,异常位置之后的代码将不被执行;
3、不管异常是否发生,finally 子句定会执行,该子句可省略;
4、构造函数即使发生异常,也会构造出对象(异常之后的赋值用默认值填充)
传播异常:通过throws子句为方法声明异常,将责任转给方法调用者
void 上课() throws 学生生病,学生上厕所{...上课过程...}
void a() throws IOException,Exception{...} //a声明异常
void b() throws IOException,Exception{...a()...} //a的调用者要么声明
void c() {...try{a();} //a的调用者要么处理
catch(IOException x){...}
catch(Exception x){...} ...}
注:1、声明异常,只是提醒该方法的调用者可能产生异常,只是将异常传给调用者,调用者可以继续声明(形成异常的传播链),或者处理。
2、注意区分throws和throw,前者用于方法声明,后者用于主动抛出异常对象。throw包含return的作用,故throw后不能放置语句。
3、异常从声明到catch捕获必须形成完整的传播链,否则异常发生时,将产生运行时错误。
自定义异常:
1、自定义异常类必须是Throwable类的子类,一般以Exception作为超类;
2、定义时要考虑在异常对象中要记录哪些信息,以方便后续行实施;
3、自定义异常对象的创建条件由程序员设定,故一般需要手工创建和外抛异常对象。
java异常的分类:检查型异常和非检查型异常
- 非检查型异常(虚拟机异常),由JVM自动创建和传播。
包括:
Error及其子类:指较为严重的灾难性错误,如虚拟机错误、IO错误、CPU错、内存错、库连接错等。
RuntimeException及其子类:如数组下标越界、除零错、非法输入错等。 - 检查型异常(程序性错误),必须声明或处理,否则编译错。
非检查型异常可自动创建和传播,而检查型异常必须有try或throws子句时才能创建或传播。即:若方法可能产生检查型异常,则必须用try或throws,否则编译错。
断言
断言是一种永真的逻辑表达式,目前断言机制主要用于回归测试。
断言的语法格式:
assert(b_exp1); 或 assert(b_exp1):info;
注:1、若断言为假,则抛出AssertionError异常,报错。
2、注释语句不能执行,断言可以执行。
断言的打开和关闭:
Java -ea 类名.class //启用断言
Java -da 类名.class //关闭断言
断言适用场合:
内部不变式、控制流不变式、前置断言、后置断言、类不变式。