Java Exception
异常在所有开发语言中,都是架构设计中不可或缺的一部分,非常重要,那么在Java开发语言中又是如何设计处理的呢?
1. 异常设计概览
在Java中 所有异常的父类是 Throwable,一切的异常子类都是基于它扩展的。
这里我们简单通过源码分析下:
/**
* 异常是所有error和exception的父类,也是基础。只有throwable以及子类的实例才能被虚拟机或者throw 关键字 抛出
* The {@code Throwable} class is the superclass of all errors and
* exceptions in the Java language. Only objects that are instances of this
* class (or one of its subclasses) are thrown by the Java Virtual Machine or
* can be thrown by the Java {@code throw} statement. Similarly, only
* this class or one of its subclasses can be the argument type in a
* {@code catch} clause.
* checkException 检查异常 不是RuntimeException子类或者Error子类,
* 换句话说 异常可以分为检查性异常 和 非检查性异常
* For the purposes of compile-time checking of exceptions, {@code
* Throwable} and any subclass of {@code Throwable} that is not also a
* subclass of either {@link RuntimeException} or {@link Error} are
* regarded as checked exceptions.
*
* <p>Instances of two subclasses, {@link java.lang.Error} and
* {@link java.lang.Exception}, are conventionally used to indicate
* that exceptional situations have occurred. Typically, these instances
* are freshly created in the context of the exceptional situation so
* as to include relevant information (such as stack trace data).
* 一个throwable 包含了异常发生创建时的快照 同时也包含了关于这个错误(异常)更多的信息
* 异常可以被其他异常传播 最后它还可以包含原因cause(另一个异常导致这个异常的原因) 这样不停的传播 就形成了一个异常链
* <p>A throwable contains a snapshot of the execution stack of its
* thread at the time it was created. It can also contain a message
* string that gives more information about the error. Over time, a
* throwable can {@linkplain Throwable#addSuppressed suppress} other
* throwables from being propagated. Finally, the throwable can also
* contain a <i>cause</i>: another throwable that caused this
* throwable to be constructed. The recording of this causal information
* is referred to as the <i>chained exception</i> facility, as the
* cause can, itself, have a cause, and so on, leading to a "chain" of
* exceptions, each caused by another.
* 异常发生的一个原因是它被构建在一个低层抽象之中,由于低层错误导致了上层操作失败,
* 让低层将错误抛出去是一个差劲的设计,因为它和上层不相关,这样做将上层和实现细节关联起来了,假设低层异常是一个检查性异常,抛出一个包装异常
* 允许上层和调用方交流失败的详细信息 而不是导致任何缺点,它在没有改变api的情况下保证了上层实现的灵活性
* <p>One reason that a throwable may have a cause is that the class that
* throws it is built atop a lower layered abstraction, and an operation on
* the upper layer fails due to a failure in the lower layer. It would be bad
* design to let the throwable thrown by the lower layer propagate outward, as
* it is generally unrelated to the abstraction provided by the upper layer.
* Further, doing so would tie the API of the upper layer to the details of
* its implementation, assuming the lower layer's exception was a checked
* exception. Throwing a "wrapped exception" (i.e., an exception containing a
* cause) allows the upper layer to communicate the details of the failure to
* its caller without incurring either of these shortcomings. It preserves
* the flexibility to change the implementation of the upper layer without
* changing its API (in particular, the set of exceptions thrown by its
* methods).
* 另一个cause是方法抛出异常必须符合通用接口,而通用接口不允许直接抛出
* <p>A second reason that a throwable may have a cause is that the method
* that throws it must conform to a general-purpose interface that does not
* permit the method to throw the cause directly. For example, suppose
* a persistent collection conforms to the {@link java.util.Collection
* Collection} interface, and that its persistence is implemented atop
* {@code java.io}. Suppose the internals of the {@code add} method
* can throw an {@link java.io.IOException IOException}. The implementation
* can communicate the details of the {@code IOException} to its caller
* while conforming to the {@code Collection} interface by wrapping the
* {@code IOException} in an appropriate unchecked exception. (The
* specification for the persistent collection should indicate that it is
* capable of throwing such exceptions.)
* cause可以通过两种方式和throwable关联起来,
* 1. 将cause作为构造器的一个参数
* 2. 使用initCause方法
* 那些希望cause与其关联起来的 New throwable 应该提供一个cause参数的构造方法并委托或者间接给一个Throwable 构造方法
* <p>A cause can be associated with a throwable in two ways: via a
* constructor that takes the cause as an argument, or via the
* {@link #initCause(Throwable)} method. New throwable classes that
* wish to allow causes to be associated with them should provide constructors
* that take a cause and delegate (perhaps indirectly) to one of the
* {@code Throwable} constructors that takes a cause.
*
* Because the {@code initCause} method is public, it allows a cause to be
* associated with any throwable, even a "legacy throwable" whose
* implementation predates the addition of the exception chaining mechanism to
* {@code Throwable}.
*
* <p>By convention, class {@code Throwable} and its subclasses have two
* constructors, one that takes no arguments and one that takes a
* {@code String} argument that can be used to produce a detail message.
* Further, those subclasses that might likely have a cause associated with
* them should have two more constructors, one th