第十章:异常的捕获和处理
1异常描述
1.1认识异常
(1)认识异常
异常是指程序在运行过程中出现的非正常情况,例如用户的输入错误,除数为零,文件不存在,数组下标越界等。
(2)Java异常体系结构
Java中的异常有很多种类型,异常在Java中被封装成了各种异常类,Java的异常体系结构
所有的异常类都是Throwable类的子类,它派生出两个子类,Error类和Exception类。
Error类:是系统的重大错误,通常这类错误修复很麻烦,常用的解决办法是让程序安全退出
Exception类:由Java应用程序抛出和处理的严重错误,Exception类的不同子类对应不同类型异常。其又可以被分为两种异常:
(1)不受检异常:unchecked异常,包括RuntimeException
及其所有子类
(2)受检异常:checked异常,指除了不受检异常外,其他继承于Exception类的异常。
1.2Java异常处理机制
1.2.1异常处理
Java的异常处理机制类似于人们对可能发生的意外情况进行预先处理的方式。如果发生异常那么程序会按照预定的处理方式对异常进行处理。处理完后程序会继续执行,如果没有处理异常,那么程序将会终止运行。
Java中异常处理机制依靠于 try,catch,throw,throws,finally
这五个关键字。
1.2.2捕获异常
(1)使用try-catch
处理异常
把可能出现异常的代码放在try块中,并使用catch语句块捕获异常。
(2)使用try-catch-finally
处理异常
try-catch-finally
语句块组合使用时,无论try
块中是否发生异常,finally
语句块中的语句都会被执行。
(3)使用多重catch
处理异常
当一段代码可能引发多种类型的异常时,可以在一个try语句块后面跟随多个catch
语句块,分别 处理不同类型的异常。
注意:catch
语句块的顺序排列一定要是从子类到父类的,最后一个一般是Exception类。(因为,在异常处理的过程中,catch
语句块的执行顺序是从上而下的,系统检测每一个catch
语句块处理异常类型,并执行第一个与异常类型匹配的catch
语句块,所以将父类放到前面,后面的异常将不会被处理。)
总的来说:异常处理的顺序和匹配的原则很重要,子类异常应该放到前面,父类异常应放到后面,以确保正确的异常处理顺序
1.2.3抛出异常
(1)使用throws声明异常
try-catch-finally
处理的是一个方法内部发生的异常,在方法内部直接捕获并处理。如果在一个方法体内抛出了异常,并希望调用者能够及时处理捕获的异常,Java语言中通过关键字throws
声明某个方法可能抛出的各种异常,以通知调用者。throws
可以同时声明多个异常,之间用逗号隔开。
(2)使用throw抛出异常
在Java中,可以使用throw
来自行抛出异常。
(3)throw与throws的区别
- 作用不同:throw用与程序员自行产生并抛出异常,throws用于声明该方法内抛出了异常
- 使用位置不同:throw位于方法体内部,可以作为单独的语句使用;throws必须跟在方法参数列表的后面,不能单独使用
- 内容不同:throw抛出一个异常对象,只能是一个;throws后面跟异常类,可以有多个
1.2.4自定义异常
当JDK中的异常类型不能满足程序的需要时,可以自定义一个异常类。使用自定义异常类步骤:
- 定义异常类,并继承
Exception
或者RuntimeException
- 编写异常类的构造方法,向父类构造方法传入异常描述信息,并继承父类的其他实现方法
- 实例化自定义异常类对象,并在程序中使用throw抛出
1.2.5异常链
异常链(Exception Chaining)是指在一个异常的构造函数中调用另一个异常的构造函数,将另一个异常作为自己的cause(原因)传递进去。这样做的目的是为了保留原始异常的信息,并将其传递到更高级别的异常中。
通过异常链,我们可以在不丢失原始异常信息的同时,将异常的上下文传递到更高级别的异常中,方便对异常进行追踪和处理。
本章问题:(以自己的理解为基础)
-
什么是异常,运行时异常,编译时异常
异常:是一种表示程序运行中出现错误或者异常情况的对象。当程序出现异常时,通常会抛出一个异常对象,这个异常对象会被传递给调用栈中的其他代码进行处理。
运行时异常:是Java中的一种异常类型,也称为非受检异常。它是在程序运行过程中由于逻辑错误引发的异常。非受检异常可以在异常处理中忽略。
编译时异常:是Java中的一种异常类型,也称为受检异常。与非受检异常相对应,它是在程序的编译过程中出现的错误,编译时异常会在编译阶段被检测出来,并且必须进行处理,否则程序无法进行运行。
-
如何处理异常
在Java中我们通常通过 catch finally try throw throws
这五个关键字进行对于异常的处理问题,通常又通过(1)使用try-catch
处理异常(2)使用throw抛出异常(3)使用finally块这三种方法进行对于异常的处理。
- 什么是checked异常,什么是unchecked异常
checked异常也称为受监测异常(是编译时异常)这类异常通常不需要强制进行处理
unchecked异常也称为非受检测异常(运行时异常)这里异常需要强制进行处理,否则程序将不能成功进行运行。
- 构造方法可以throws异常吗,对子类有影响吗,什么情况下有影响
构造方法可以抛出异常,和普通方法一样,可以使用throw关键字进行声明可能抛出的异常情况。当一个构造方法抛出异常时,该异常会向上一级调用者传播,如果没有合适的异常处理机制,最终会导致程序的终止。
对于子类而言,当父类的构造方法声明了可能抛出的异常时,子类的构造方法需要遵循一定的规则:(1)如果子类的构造方法不抛出异常,那么它可以调用父类的构造方法,但是需要确保父类构造方法中的异常能够得到处理,一般通过使用try-catch语句块来处理可能的异常。(2)如果子类的构造方法抛出异常,那么它需要再方法声明中使用throw关键字声明异常,同时需要再方法体内部调用父类的构造方法,并确保父类构造方法中的异常能够得到处理。
总得来说,当父类的构造方法声明了可能抛出的异常时,子类的构造方法需要将这些异常适当的处理或者继续传播,以确保异常都能得到妥善的处理,避免程序的以外终止。
- 能throw一个error吗
在Java中,可以使用throw关键字抛出一个error类型的错误,但是通常不建议直接抛出一个error类型的错误。
error错误是Throwable中的子类,代表了严重的错误或者系统级的问题,通常由Java虚拟机抛出,这些错误通常是不能被恢复的,因此不建议在应用程序中主动抛出error类型的错误。
- finally为什么不返回catch中的return,而是返回finally中的return
在Java中,finally
块中的return
语句会覆盖掉try
或catch
块中的return
语句。这是因为finally
块中的代码会在try
或catch
中的代码执行完毕后无论是否发生异常都会执行,以确保资源的释放和清理工作。
finally
块中的return
语句会直接返回相应的值,并结束方法的执行,不会再执行在try
或catch
块中的后续代码。
这样设计的原因是为了保证在方法执行完毕前能够执行所需的清理操作,无论方法是否发生异常。这样做可以确保资源得到正确释放,避免资源泄漏和不可预期的行为。
- 自定义异常,自定义异常要注意什么地方(规则,要求什么的)
应当注意以下几点,继承合适的异常类,提供构造方法,添加可选地错误码和错误信息属性,重写可选的toString()
方法,遵循命名规则,考虑异常处理机制