Java经常使用异常整理

填坑,整理下Java的经常使用异常。正确使用异常在实际编码中很是重要,但面试中的意义相对较小,由于对异常的理解和应用很难经过几句话或几行代码考查出来,不过咱们至少应答出三点:异常类的继承关系、经常使用异常类、经常使用异常类的使用场景,下文将围绕这三点介绍。git

异常类的继承关系

image.png
image.png

Java中,全部异常都继承自Throwable类(一个完整可用的类)。总体上分为Error、Exception两个大类,Exception大类又分为UncheckedException(继承于RuntimeException)和CheckedException(继承于Exception,但不继承于RuntimeException)。github

为了帮助理解,我在每一个类别下都给出了两个经常使用子类,如Error包括OutOfMemoryError、AssertionError等;UncheckedException包括NullPointerException、IllegalArgumentException;CheckedException包括IOException、InterruptedException。面试画异常类的继承关系时,要求能清楚的说明几个类别并分类别举几个经常使用的异常类。面试

经常使用异常类

下面分类别扩充一下经常使用的异常类,字典序排序:算法

类别 经常使用异常类
Error AssertionError、OutOfMemoryError、StackOverflowError
UncheckedException AlreadyBoundException、ClassCastException、ConcurrentModificationException、IllegalArgumentException、IllegalStateException、IndexOutOfBoundsException、JSONException、NullPointerException、SecurityException、UnsupportedOperationException
CheckedException ClassNotFoundException、CloneNotSupportedException、FileAlreadyExistsException、FileNotFoundException、InterruptedExceptionIOException、SQLException、TimeoutException、UnknownHostException

须要着重理解的是UncheckedException。json

上述异常类都是很常见的,但其中几个异常类设计的很差,须要注意:安全

  • ConcurrentModificationException:实现“快速失败”的机制,但实际上,“快速失败”机制自己仍然没法保证并发环境下安全性,参考源码|从源码分析非线程安全集合类的不安全迭代器。所以,虽然该异常很常见,不要去依赖它。
  • JSONException:常见于json字符串解析失败的状况,但遮蔽了大量的失败细节,每每很难根据该异常做出处理。若是项目中大量使用json,建议使用第三方的json解析库,如gson等。
  • UnsupportedOperationException:这是一种编码上的恶性妥协,常常在抽象类的成员方法中被用户主动抛出,表示该方法还未实现等,但因为是UncheckedException,运行期才可以发现,彻底无益于编码期间的安全性。本身编码时尽可能不要使用。
  • SQLException:与JSONException缘由类似,但其遮蔽的失败细节范围更广。同时,SQLException仍是一个CheckedException,在不能解决问题的状况下,又使代码变的臃肿不堪。建议同。若是作Java Web开发,热门的ORM库都能解决上述问题。

经常使用异常类的使用场景

经常使用异常仍是有点多,下面分别讲解上述三个类别的使用场景,并在每一个类别中选一个例子进行讲解。并发

Error

Error一般描述了系统级的错误,而且程序猿没法主动处理——固然,系统级错误也有可能由代码间接致使,这不在咱们的讨论范围内。发生系统级错误的时候,系统环境已经不健康了,所以,Error不强制捕获或声明,也就是不强制处理,通常状况下只须要把异常信息记录下来(若是能记下当时的系统快照更好)。源码分析

OutOfMemoryError

当可用内存不足时,会由JVM抛出OutOfMemoryError。通常由三种缘由致使:编码

  • 堆设置太小,不知足正常的内存需求
  • 代码中存在内存泄露,占用了大量内存而不能被回收
  • 选择的GC算法与某些极端的应用场景不匹配,内存碎片过多,没有足够大的连续空间分配给对象

JVM抛出OutOfMemoryError前,会尝试进行一次Full GC,若是GC后可用内存仍是不足,才会抛出OutOfMemoryError。所以,这时程序猿必然没法主动处理这一问题,只能等程序崩溃后再去查证缘由。线程

查证OutOfMemoryError的技巧足以单开一篇文章了,本文不做深刻。

UncheckedException

严格来讲,Error也能够被划归UncheckedException,但咱们更习惯用UncheckedException描述运行期发生,一般因为代码问题直接引发的程序相关的错误,而且程序猿没法主动处理。注意区分,系统级错误都应该用Error描述。UncheckedException发生的大部分状况是代码写挫了,所以,UncheckedException也不强制捕获或声明,也就是不强制处理,通常状况下记下日志便可

不一样的是,若是可能,要保证UncheckedException是可控的(在异常被动抛出前检查并主动抛出)

JSONException就是不可控的。

NullPointerException

NullPointerException是最多见的UncheckedException。若是在一个空指针上引用方法或变量等,则运行期会抛出NullPointerException。空指针让程序变的不可控:若是任由空指针在程序运行期随意传递、使用,咱们将没法肯定程序的行为,也没法肯定捕获NullPointerException时程序所处的状态。

解决这一问题的方法很简单:

  • 尽早检查并主动抛出异常
  • 单独、提早处理边界条件
  • 尽可能不使用null表示状态,特别是在集合中

前两条原则通用于大部分UncheckedException,可参考String#toLowerCase()的例子。第三条原则须要在代码的健壮与简洁之间作出权衡,优先保证简洁清晰,须要健壮再去健壮。

CheckedException

猴子对CheckedException的理解不到位,若是各位有更好的理解但愿能交流一下。如下讲猴子“不到位”的理解。

CheckedException描述了外部环境致使的不太严重的错误,程序猿应该主动处理。注意与系统级错误区分,系统级错误一般是不可恢复的。所以,CheckedException强制捕获或声明,程序猿必须处理。记录日志,包装后再次抛出,在方法签名中声明,是三种最多见的作法。

同UncheckedException同样,CheckedException也要保证是可控的。对CheckedException的可控性要求更高,不只要主动检查,还要在捕获到异常时,做出合适的处理。

不过,猴子认为大量CheckedException的存在就是个错误。好比FileAlreadyExistsException,更应该由用户主动检查发现,而不该该依赖于异常。对于能够处理的异常,本质上至关于控制流问题,用异常去表达反而让控制流变模糊。不过有时候猴子写小项目,也会为了简化代码,直接将相关异常声明在方法签名中,并一路声明干到main方法。恩,everything is a trade-off。

IOException

产生IOException的缘由很是多,但不少时候咱们并不关心细节缘由,由于文件系统是一个不太可控的因素,这时咱们能够以IOException为粒度处理;某些须要关心细节的异常状况,则应使用IOException的子类,以分状况处理。

前面总结的FileAlreadyExistsException、FileNotFoundException、UnknownHostException等,都是IOException的子类。这三种异常刚好都是能够处理的。

挖坑,InterruptedException也至关重要,后面要专门写一篇来整理。

总结

实际的编码工做中,咱们应正确的使用异常表达代码设计,并尽量使用JDK提供的异常类。JDK内置了很是多的异常类,咱们只须要掌握一些经常使用的异常类,而后触类旁通。


本文连接:Java经常使用异常整理
做者:猴子007
出处:monkeysayhi.github.io
本文基于 知识共享署名-相同方式共享 4.0 国际许可协议发布,欢迎转载,演绎或用于商业目的,可是必须保留本文的署名及连接。

相关文章
相关标签/搜索