之前一直都知道异常分类可以分为受检和非受检,关于二者区别也大致了解但是,一直觉得没有很透彻地搞清楚,以至于有时候心里很纠结,这次下决心一定要弄清楚了。

二者的关键区别在于:用户是否是能在发生异常时做一些恢复处理。

举个例子说明:

对于受检异常中的文件不存在异常,我们写的文件读写程序,很有可能出现文件不存在的情况,那么一旦发生,我们需要catch住再做处理,比如给出提示文件不存在之类的提示。但是对于非受检异常比如数组越界或者除零异常,这种属于一种程序的bug,按照道理来讲是程序员编程不当导致的,这种bug一旦发生应该消除。

所以受检和非受检的异常,他们的性质是不同的。受检异常程序员是可以处理的,或者说这种异常是允许发生的,是一种意料之内的情况,只不过程序员需要去处理,比如文件不存在这种客观情况。道理上来说,文件存不存在都是合理的,都是客观存在的一种情况,只不过我们的文件读写程序通常都针对文件存在的情况,所以这里受检的异常只是让我们额外处理文件不存在的情况。但是非受检异常的性质就不一样了,比如越界异常,这种就是程序的bug,我们通常都无法做出正确的处理,甚至说这种bug就不应该被catch住,就应该被抛出来,才能被发现,才能被修复。所以受检异常是一种合理的情况,但是非受检异常就是一种bug,是不应该发生的。这就是二者在逻辑上的区别。

我觉得明白了这种概念上的区别,才能很好理解这两种异常。

从语法上来说,受检异常是exception类的子类但不能是runtimeexception类的子类。如果方法里面抛出了受检异常,那么方法的签名必须throws这个异常,调用方也会被强制try-catch处理这个异常,这是编译级别的限制。如果是runtimeexception或者error的子类那就是非受检的,这种异常在方法内抛出不需要在签名处throws。语法层面的支持和上面介绍的概念上的区别也是可以对齐的。

 

 

其实对于使用受检还是非受检是有争议的 这里介绍一个经验

对于方法定义 

仅当下列情况之一才使用受检

1 需要使用异常定义返回值 调用端可以做一些分支处理

2 调用端可以从异常恢复 可做降级等(其实1是特殊的2)

其余情况都用非受检

因为受检异常会污染api 使得代码里充斥着try catch

对于可能跑出异常的方法的调用

如果可以恢复就catch住处理 否则就上抛一个runtime异常 最终交给一个上游统一处理 比方说统一记录日志 记录打点等等

不可恢复指的是这次调用必须返回结果 否则无法完成业务流程 这种情况即使catch住也没用 因为没法恢复 所以不用catch