Java 异常总结

Java 程序设计语言提供了三种可抛出结构(throwable):程序员

  • 受检异常(checked exception)
  • 运行时异常(run-time exception)
  • 错误(error)

受检异常

在决定使用受检的异常或者是未受检的异常时,主要的原则是:若是指望调用者可以适当的恢复,对于这种状况就要使用受检异常。经过抛出受检异常,强迫调用者在一个 catch 子句中处理该异常,或者将它传播出去。编程

未受检异常

有两种未受检的可抛出结构:运行时异常(run-time exception) 和错误。并发

在行为上二者是等同的:它们都是不须要也不该该被捕获的可抛出结构,这种异常每每属于不可恢复的情形,继续执行下去有害无益。若是程序没有捕捉到这样的可抛出结构,将会致使当前线程中止(halt),并出现适当的错误信息。框架

用运行时异常来代表编程错误。学习

大多数的运行时异常表示前提违例(precondition violation)。所谓前提违例是指 API 的客户没有遵照 API 规范创建的约定。你实现的全部未受检的抛出结构应该是 RuntimeException 的子类。线程

对于能够恢复的状况,使用受检的异常;对于程序错误,则使用运行时异常。设计

异常也是一个彻底意义上的对象,能够在它上面定义任意的方法。该方法的主要用途是为捕获异常的代码而提供额外的信息,特别是关于引起这个异常条件的信息。调试

优先使用标准的异常

专家级程序员和缺少经验的程序员的一个最主要的区别就是,专家追求而且一般页呢可以实现高度的代码重用。日志

代码重用是值得提倡的,这是一条通用的规则,异常也不例外。code

Java 平台类库提供了一组基本的未受检的异常,他们知足了绝大多数 API 的异常抛出须要。

重用现有的异常有多方面的好处

  • 它使你的 API 更加易于学习和使用,由于它与程序员熟知的习惯用法是一致的
  • 对于用到的这些 API 程序而言, 可读性更好,由于不会出现不少程序员不熟悉的异常。

IllegalArgumentException 是最常常被重用的。由于接收对象的状态而使调用非法,一般就会抛出这个异常。能够这么说,全部错误的方法调用均可以被归结为非法参数或者非法状态

IllegalStateException 是由于接收对象的状态而使调用非法,一般就会抛出这个异常。

可是,其余还有一些标准异常也被用于某些特定状况下的非法参数和非法状态。

如,NullPointerException 针对传入参数为 null 的状况。IndexedOutOfBoundsException 针对

此外,还有一些异常,如 ConcurrentModificationException。若是一个对象被设计为专用于单线程或者与外部同步机制配合使用,一旦发现它正在(或者已经)被并发的修改,就应该抛出这个异常。

另一个UnsupportedOperationException 。若是对象不支持所请求的操做,就会抛出这个异常。若是某个异常可以知足你的须要,就不要犹豫,使用就是,不过,必定要确保抛出异常的条件与该异常的文档中描述的条件一致。

抛出与抽象对应的异常

若是方法抛出的异常与它所执行的任务没有明显的联系,这种情形将会令人不知所措。

为避免此类问题,更高层的实现应该捕获低层次的异常,同时抛出能够按照高层抽象进行解释的异常。这种作法称为异常转译(exception translation)。

不要忽略异常

无论异常表明了可预见的异常条件,仍是编程错误,用空的 catch 块忽略它,将会致使程序在遇到错误的状况下悄然的执行下去。而后,有可能在将来的某个点上,当程序不能容忍与错误源明显相关的问题时,它就会失败。

正确的处理异常功能可以完全挽回失败。只要将异常传播给外界,至少会致使程序迅速的失败,从而保留了有助于调试该失败条件的信息。

不建议使用 printStackTrace()

就是printStackTrace()打印出的堆栈日志跟正常输出或者业务代码执行日志是交错混合在一块儿的,在并发日志输出多的状况下,查看异常日志就变动的很是困难,由于一块日志都不在一块儿了。

printStackTrace()默认使用了System.err输出流进行输出,与System.out是两个不一样的输出流,那么在打印时天然就造成了交叉。再就是输出流是有缓冲区的,因此对于何时具体输出也造成了随机。

看到这里就明白了,若是想简单的让输出顺序话,给printStackTrace()指定一个输出流就能够了,例如printStackTrace(System.out)

在项目中通常都是使用logback、log4j这类框架统一打印日志,好处多多。