异常的类型和使用目的及场景
异常的类型
Error
在Java中, 由系统环境问题引起的异常,一般都继承于Error类。
对于Error类:
- 一般开发者不要自定义Error子类,因为它代表系统级别的错误。与一般的程序无关。
- 在Java异常处理机制中,Error不强制捕获或声明,也就是不强制处理。因为程序本身对此类错误无能为力。一般情况下我们只要把堆栈跟踪信息记录下来就行。
程序在执行过程中所遇到的硬件或操作系统的错误。错误对程序而言是致命的,将导致程序无法运行。常见的错误有内存溢出,jvm虚拟机自身的非正常运行,calss文件没有主方法。程序本生是不能处理错误的,只能依靠外界干预。Error是系统内部的错误,由jvm抛出,交给系统来处理。
Exception
在Java中,除了系统环境问题引起的异常,一般都继承于Exception类。Exception分为RuntimeException和Checked Exception。Checked Exception必须要捕获或声明。而RuntimeException不强制。
对于Exception类:
- 如果你创建了一个异常类型,直接继承于Exception,那么这个异常类型将属于检查异常(Checked Exception)。
是程序正常运行中,可以预料的意外情况。比如数据库连接中断,空指针,数组下标越界。异常出现可以导致程序非正常终止,也可以预先检测,被捕获处理掉,使程序继续运行。
Exception中又包含编译时异常和运行时异常。
编译时异常
又叫可检查异常,通常时由语法错和环境因素(外部资源)造成的异常。比如输入输出异常IOException,数据库操作SQLException。其特点是,Java语言强制要求捕获和处理所有非运行时异常。通过行为规范,强化程序的健壮性和安全性。
在Java中,直接或间接因为“资源”问题引起的异常,一般属于检查异常(Checked Exception) 。检查异常继承于Exception,而不继承于RuntimeException。
对于检查异常:
- 必须捕获或声明
- 交给关心这个异常的方法处理
- 异常处理器应该引导用户接下来怎么办,至少做到安全退出
运行时异常
在Java中,由于接口方法使用不当造成的异常,一般属于RuntimeException,也就是运行时异常。
对于RuntimeException:
- 如果你调用服务方法的方式不正确,你应该马上修改代码,避免发生RuntimeException
- 如果是用户方法调用你的方法的方式不正确,你应该立刻抛出RuntimeException,强制让使用者修正代码或改变使用方式,防止问题蔓延
- 一般情况下,不要捕获或声明RuntimeException。因为问题在于你的程序本身有问题,如果你用异常流程处理了,反而让正常流程问题一直存在
又叫不检查异常RuntimeException,这些异常一般是由程序逻辑错误引起的,即语义错。比如算术异常,空指针异常NullPointerException,下标越界IndexOutOfBoundsException。运行时异常应该在程序测试期间被暴露出来,由程序员去调试,而避免捕获。
使用异常的目的
- 当异常发生时,能够将异常通知给编程人员或者用户。
- 然后使本来已经中断的程序以适当的方式继续运行,或者退出。并且能够保存用户的当前操作,或者进行数据回稳。
- 最后再把占用的资源释放掉
异常的使用场景
主要有三个场景
-
调用方(Client)破坏了协议
说白了就是调用方法时没有按照约定好的规范来传参数,典型的比如参数是个非空集合却传入了空值。这种破坏协议的还可以细分两类,一类是调用方从接口形式上不易觉察的规则但需要在出现时给调用方些强提示,带些信息上去,这时异常就是特别好的方式;另一类是调用方可以明确看到的规则,正常情况会正常处理协议,不会产生破坏,但可能因为bug导致破坏协议。 -
(Method)知道有问题,但自己处理不了
这里"有问题",可能是调用方破坏了协议,但是单独提出来是要从被调用方出发考虑,比如Method内部有读取文件操作,但发现文件并不存在 -
预料不到的情形
空指针异常、数组越界是这种典型的场景,一般是由于有代码分支被忽略