关于JAVA的异常基类Throwable,及异常链的产生原由
Throwable类总共提供了3个属性,分别为:
String detailedMessage;
Throwable cause;
StackTraceElement[] stackTrace

其中第一个记录了异常的详细信息
第二个表示抛出该异常的基类
第三个表示异常的方法调用序列,从“方法调用处”直到“异常抛出处”
最下方先打印方法最早调用处,最上端打印异常抛出的地方

它的每一个构造方法都会调用一个fillInStackTrace()方法,该方法将在异常堆栈跟踪中填充。此方法在Throwable对象记录有关当前线程堆栈帧的状态。

它另外提供了一个initCause(Throwable cause)方法
该方法将cause赋给该对象的成员属性
两种情况下不能赋值:
第一种情况:如果当前对象已经有cause,则不允许覆盖,并且会抛出不允许覆盖cause的异常
第二种情况:如果cause与当前对象是同一个的话,也不允许覆盖,并且抛出自身不允许迭代的异常


它的ToString方法是这样的:
首先获取该异常对象的类名,然后获取该对象的详细出错信息detailedMessage,如果有的话,则将两者组合在一块
getClass().getName():+detailedMessage

其实它更有用的应该属于它的PrintStackTrace()方法
如果不指定输出流,则默认为System.err
该方法首先会打印当前对象,调用该对象的ToString()方法
然后获取当前对象的方法调用序列,并以\t at 开头这样的打印
然后判断是否存在异常缘由,如果有的话,则调用printStackTraceAsCause()方法
该方法首先会标记异常缘由的方法轨迹与父异常的方法轨迹,并且将异常缘由的方法轨迹的长度一步步的减小
然后仿照打印父异常的方法,先打印caused by 该异常缘由,然后打印异常缘由的方法执行轨迹,最后,判断异常缘由的方法轨迹剩下的长度是否为0,如果不为0,则打印:
\t... 异常缘由的方法轨迹剩下的长度 more


异常的方法轨迹打印顺序是这样的
从上至下 依次为
异常抛出处直到方法调用处
最下方为方法调用处,最上方为异常抛出的地方

打印异常方法printStackTrace()方法提供的信息可以通过getStackTrace()方法来直接调用
这个方法将返回一个由栈轨迹中的元素所构成的数组。其中每个元素表示栈中的一帧。元素0是栈顶元素,也就是调用序列中的最后一个方法调用(也即异常的发送和抛出地方),最后一个元素是方法的第一个调用处
所以如果打印异常轨迹的时候,从上往下依次为异常的抛出处==》最初的方法调用处

有趣的是,在Throwable的子类中,只有三种基本的异常类提供了带异常链参数的方法,分别为Exception,Error,RuntimeException 严格讲 RuntimeException属于Exception
而其他异常只能通过initCause(Throwable cause)方法来构造异常链