6-2 错误与异常处理

一、错误与异常

  Error和Exception是接口,下图中虚线圈起来的部分属于unchecked exception,剩余部分属于checked exception,unchecked类型编译器不管,其他的编译器会check,必须被捕获或者被抛出。
在这里插入图片描述

  错误一般是指内部系统的问题,程序员一般对此无能为力,只能让程序gracefully地退出;异常则是程序导致的问题,可以捕获、处理。

二、异常处理

1、异常

  异常指程序中出现的非正常事件。异常可以通过异常处理程序处理,也可以抛出异常、将信息传递给上层调用者,然后退出。

  try-catch异常处理机制可以将正常的代码与异常处理代码分离开,代码结构清晰。

2、异常的分类

  异常分为checked、unchecked两类。unchecked包含RuntimeException及其子类,这是由程序员在代码中处理不当造成的,可以由程序员检查去避免,例如数组越界、空指针;checked是外在问题导致的,即使程序员去检查也不一定能避免(例如读写文件,代码中检查了文件是否存在,但可能运行时刚检查完文件是存在的,文件就被删除了),需要编译器去检查。

  对于unchecked异常,不需要使用try-catch进行处理或者抛出,编译也会通过,但运行时会出错。常见的有数组越界、空指针、不合法参数、类型转换等。

  对于checked异常,要么处理、要么抛出,编译器可帮助检查checked异常是否被处理或抛出了。

  处理checked异常的一些关键字:try、catch、finally、throws、throw。try-catch-finally用来捕获和处理异常,throws表示该方法可能抛出异常,throw用来抛出异常。

  如果对于一个异常无能为力,就用unchecked异常,仅仅抛出异常信息即可;如果可以根据异常信息对异常进行处理、恢复,就用checked异常。例如读文件时,如果出现文件不存在的异常,可以让用户选择其他文件,然而如果出现了数组越界之类的错误,执行时是无法进行处理的。

3、声明异常

  可能抛出的checked异常需要在spec中声明,需要在签名中throws:
在这里插入图片描述

  unchecked异常则不需要写在规约中。因为这种异常是可以通过改代码避免的,还抛出个啥。

  方法应该抛出两类异常:1、调用的函数抛出的异常,并且没有进行处理;2、方法自己的代码抛出的未处理的异常。

  不建议声明unchecked类型的异常,因为这种异常要么就是没办法处理(error),要么就是可以避免的(RuntimeException)。

  回顾LSP替换原则,子类型可以替换父类型,要求子类型抛出的异常也要是父类型抛出异常的子类型或相等,不能比父类型抛出的异常更大、更宽泛。举个例子,下图就是错误的形式,因为FileNotFoundException是IOException的子类:
在这里插入图片描述

  抛出异常:找到一个或者自己构造一个Exception类;使用new构造实例,写入错误信息;使用throw抛出这个异常:
在这里插入图片描述

4、创建异常类

  checked类型:创建的类要继承(extends)自Exception类,或者Exception的子类。通常给出一个默认构造函数,和一个包含详细信息的构造函数:
在这里插入图片描述

  对于checked异常,要在可能抛出异常的方法上声明:

在这里插入图片描述

  unchecked类型:通常继承RuntimeException,在可能抛出异常的函数的签名后面不需要声明。

5、catch异常

  异常发生后,如果没有对异常的处理,就终止程序执行,在控制台打印stack trace。

  处理异常:使用try-catch语句来捕获异常:

在这里插入图片描述

  无异常时,catch中的语句不执行;若出现的异常未被catch,就需要被throw出去。

  对于一个checked异常,要么catch它,要么使用throws传递(留给client去处理)。如果父类型方法没有异常抛出,那么子类型必须处理所有的异常。当可能有多个异常需要catch时,一般子类型写前面。

6、重新抛出异常和异常链

  在catch语句中抛出更高级的异常,更方便客户端获取信息:
在这里插入图片描述

  最好做下图所示操作保留根原因:
在这里插入图片描述

7、finally

  finally部分的代码,不管异常是否被捕获,不管发生了啥,都会执行。

  一个例子,下图的try中抛出了异常,代码执行的顺序是13456;如果在3处抛出异常,执行的顺序就是135;如果在1处抛出了异常,没有catch语句去捕捉,执行顺序就是15:
在这里插入图片描述

  一个极端的例子,这里finally最后还会执行,返回值是false:
在这里插入图片描述

8、try-with-resources

  在try后面的括号里写有可能需要关闭资源的语句,在try结束后会自动对资源进行关闭,但这个资源要实现AutoCloseable接口。

在这里插入图片描述

9、堆栈追踪机制

  如果一个程序的流程是这样:main调用A,A调用B,B调用C,其在栈中结构如下:
在这里插入图片描述

  如果C中抛出了异常,JVM从栈顶开始,向下查找处理代码catch,如果找到了就处理,找不到就终止程序。

  打印出的堆栈信息如下,最上面是异常发生的地方,最下面是最开始的调用:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值