volley源码解析-Throwable类源码解析

前提知识点:

1.Serializable接口

作用:表示可序列化的语义。就是Java提供的通用数据保存和读取接口。任何类型实现了Serializeable接口,就可以被保存到文件中,或者作为数据流通过网络发送到别的地方,也可以用管道来传输到系统的其他地方。在Java中的序列化,只需要实现serializable接口,然后,你可以使用objectOutputStream将该对象保存到文件或者发送到其他主机,所有的non-transient和non-static字段都将被序列化,所有我们想自己处理的字段都因该声明为transient。

2.defaultWriteObject()和defaultReadObject(),他们做的是默认的序列化进程。

3.printWriter和printStream的区别:

printWriter主要用来操作字符流,printStream主要用来操作byte流。如果我们要读取文本文件最好用前者。String缺省都是用UNICODE进行编码,是16bit,因此printWriter写入的字符串的跨平台性好一些,用printStream可能会出现乱码。

Trowable类的作用:

在Java中,根据错误性质将运行错误分为两类:错误和异常。

  在Java程序的执行过程中,如果出现了异常事件,就会生成一个异常对象。生成的异常对象将传递Java运行时系统,这一异常的产生和提交过程称为抛弃(throw)异常。

  当Java运行时系统得到一个异常对象时,它将会沿着方法的调用栈逐层回溯,寻找处理这一异常的代码。找到能够处理这类异常的方法后,运行时系统把当前异常对象交给这个方法进行处理,这一过程称为捕获(catch)异常。

  Java中的所有异常都是由Throwable类的子类生成的对象,所有的异常类都是Throwable类的子类或子类的子类。Throwable类是Object类的直接子类,Error类和Exception类是Throwable类的两个直接子类。

1.Error类

  Error类包括一些严重的程序不能处理的系统错误类,如内存溢出、虚拟机错误、栈溢出等。这类错误一般与硬件有关,与程序本身无关,通常由系统进行处理,程序本身无法捕获和处理。

  Error类的常见子类如图1所示。

1 Error类的常见子类

2.Exception类

  有些异常在编写程序时无法预料的,如中断异常、非法存取异常等。为了保证程序的健壮性,Java要求必须对这些可能出现的异常进行捕获,并对其进行处理。

  Exception类的常见子类如图2所示。

2 Exception类的常见子类

3.RuntimeException类

  RuntimeException类是Exception类的子类。RuntimeException类的常见的子类如图3所示。

3 RuntimeException类的常见的子类

Throwable类解析:包含五个成员变量,四个构造函数,多个成员函数。

五个成员变量:

1.serialVesionUID(通过类名,接口名,成员方法及属性等生成的64位的哈希字段),作用:序列化是为保持版本的兼容性,即在版本升级时反序列化仍然保持对象的唯一性。

2.backtrace 当本地代码保存在slot中的一些栈的回溯指针。

3.detailMessage 描述异常信息。

4.cause 表示当前异常由那个Throwable引起,如果为null,表示不为其他异常引起,如果对象与自己相同表示此异常还未初始化。

5.strackTrace 描述异常轨迹数组。

四个构造函数:

1.无参构造函数:用于初始化异常轨迹数组。

2.带有一个String类型的message参数的构造函数:除了要初始化异常轨迹数组,还要初始化异常描述信息。

3.带有一个String类型的message和一个Trowable类型的cause,除了要初始化异常轨迹数组,和异常描述信息,还要初始化起因对象。

4.带有一个Trowable类型的cause。初始化异常轨迹数组,初始化起因对象,将起因对象的.toString()赋值给detailMessage。

其他成员函数的作用有:获取详细的异常描述信息,获取起因对象,初始化起因对象,字符串的表现形式(类名+异常描述信息),打印错误轨迹,打印错误轨迹的起因对象信息,填充异常轨迹,异常轨迹的深度的获取(0表示无法获取),获取指定位标的异常轨迹,获取异常轨迹数组信息并保存。

Java代码  
1package java.lang;  
2import java.io.*;  
3/** 
4*  
5* Throwable是所有Error和Exceptiong的父类 
6* 注意它有四个构造函数: 
7* Throwable() 
8* Throwable(String message) 
9* Throwable(Throwable cause) 
10* Throwable(String message, Throwable cause) 
11*  
12*/  
13public class Throwable implements Serializable {  
14      private static final long serialVersionUID = -3042686055658047285L;  
15  
16      /** 
17       * Native code saves some indication of the stack backtrace in this slot. 
18       */  
19      private transient Object backtrace;   
20  
21      /** 
22       * 描述此异常的信息 
23       */  
24      private String detailMessage;  
25  
26      /** 
27       * 表示当前异常由那个Throwable引起 
28        * 如果为null表示此异常不是由其他Throwable引起的 
29        * 如果此对象与自己相同,表明此异常的起因对象还没有被初始化 
30       */  
31      private Throwable cause = this;  
32  
33      /** 
34       * 描述异常轨迹的数组 
35       */  
36      private StackTraceElement[] stackTrace;  
37  
38      /** 
39       * 构造函数,起因对象没有被初始化可以在以后使用initCause进行初始化 
40        * fillInStackTrace可以用来初始化它的异常轨迹的数组 
41       */  
42      public Throwable() {  
43          fillInStackTrace();  
44      }  
45  
46      /** 
47       * 构造函数 
48       */  
49      public Throwable(String message) {  
50         //填充异常轨迹数组  
51          fillInStackTrace();  
52         //初始化异常描述信息  
53          detailMessage = message;  
54      }  
55  
56      /** 
57       * 构造函数,cause表示起因对象 
58       */  
59      public Throwable(String message, Throwable cause) {  
60          fillInStackTrace();  
61          detailMessage = message;  
62          this.cause = cause;  
63      }  
64  
65      /** 
66       * 构造函数 
67       */  
68      public Throwable(Throwable cause) {  
69          fillInStackTrace();  
70          detailMessage = (cause==null ? null : cause.toString());  
71          this.cause = cause;  
72      }  
73  
74      /** 
75       * 获取详细信息 
76       */  
77      public String getMessage() {  
78          return detailMessage;  
79      }  
80  
81      /** 
82       * 获取详细信息 
83       */  
84      public String getLocalizedMessage() {  
85          return getMessage();  
86      }  
87  
88      /** 
89       * 获取起因对象 
90       */  
91      public Throwable getCause() {  
92          return (cause==this ? null : cause);  
93      }  
94  
95      /** 
96       * 初始化起因对象,这个方法只能在未被初始化的情况下调用一次 
97       */  
98      public synchronized Throwable initCause(Throwable cause) {  
99         //如果不是未初始化状态则抛出异常  
100          if (this.cause != this)  
101              throw new IllegalStateException("Can't overwrite cause");  
102          
103         //要设置的起因对象与自身相等则抛出异常  
104          if (cause == this)  
105              throw new IllegalArgumentException("Self-causation not permitted");  
106          
107         //设置起因对象  
108          this.cause = cause;  
109         //返回设置的起因的对象  
110          return this;  
111      }  
112  
113      /** 
114       * 字符串表示形式 
115       */  
116      public String toString() {       
117          String s = getClass().getName();          
118          String message = getLocalizedMessage();        
119          return (message != null) ? (s + ": " + message) : s;  
120      }  
121  
122      /** 
123       * 打印出错误轨迹 
124       */  
125      public void printStackTrace() {   
126          printStackTrace(System.err);  
127      }  
128  
129      /** 
130       * 打印出错误轨迹 
131       */  
132      public void printStackTrace(PrintStream s) {  
133          synchronized (s) {  
134            //调用当前对象的toString方法  
135              s.println(this);  
136            //获取异常轨迹数组  
137              StackTraceElement[] trace = getOurStackTrace();  
138              
139            //打印出每个元素的字符串表示  
140              for (int i=0; i < trace.length; i++)  
141                s.println("	at " + trace[i]);  
142  
143            //获取起因对象  
144              Throwable ourCause = getCause();  
145              
146            //递归的打印出起因对象的信息  
147              if (ourCause != null)  
148                ourCause.printStackTraceAsCause(s, trace);  
149          }  
150      }  
151  
152      /** 
153       * 打印起因对象的信息 
154       * @param s 打印的流 
155        * @param causedTrace 有此对象引起的异常的异常轨迹  
156       */  
157      private void printStackTraceAsCause(PrintStream s,  
158                                          StackTraceElement[] causedTrace)  
159      {  
160         //获得当前的异常轨迹  
161          StackTraceElement[] trace = getOurStackTrace();  
162         //m为当前异常轨迹数组的最后一个元素位置,   
163         //n为当前对象引起的异常的异常轨迹数组的最后一个元素  
164          int m = trace.length-1, n = causedTrace.length-1;  
165         //分别从两个数组的后面做循环,如果相等则一直循环,直到不等或数组到头  
166          while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {  
167              m--; n--;  
168         }  
169          
170         //相同的个数  
171          int framesInCommon = trace.length - 1 - m;  
172          
173         //打印出不同的错误轨迹  
174          s.println("Caused by: " + this);  
175          for (int i=0; i <= m; i++)  
176              s.println("	at " + trace[i]);  
177          //如果有相同的则打印出相同的个数  
178          if (framesInCommon != 0)  
179              s.println("	... " + framesInCommon + " more");  
180  
181         //获得此对象的起因对象,并递归打印出信息  
182          Throwable ourCause = getCause();  
183          if (ourCause != null)  
184              ourCause.printStackTraceAsCause(s, trace);  
185      }  
186  
187      /** 
188       * 打印出错误轨迹 
189       */  
190      public void printStackTrace(PrintWriter s) {   
191          synchronized (s) {  
192              s.println(this);  
193              StackTraceElement[] trace = getOurStackTrace();  
194              for (int i=0; i < trace.length; i++)  
195                  s.println("	at " + trace[i]);  
196  
197              Throwable ourCause = getCause();  
198              if (ourCause != null)  
199                  ourCause.printStackTraceAsCause(s, trace);  
200          }  
201      }  
202  
203      /** 
204       * 打印起因对象的信息 
205        */  
206      private void printStackTraceAsCause(PrintWriter s,  
207                                          StackTraceElement[] causedTrace)  
208      {  
209          // assert Thread.holdsLock(s);  
210  
211          // Compute number of frames in common between this and caused  
212          StackTraceElement[] trace = getOurStackTrace();  
213          int m = trace.length-1, n = causedTrace.length-1;  
214          while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {  
215              m--; n--;  
216          }  
217          int framesInCommon = trace.length - 1 - m;  
218  
219          s.println("Caused by: " + this);  
220          for (int i=0; i <= m; i++)  
221              s.println("	at " + trace[i]);  
222          if (framesInCommon != 0)  
223              s.println("	... " + framesInCommon + " more");  
224  
225          // Recurse if we have a cause  
226          Throwable ourCause = getCause();  
227          if (ourCause != null)  
228              ourCause.printStackTraceAsCause(s, trace);  
229      }  
230  
231      /** 
232       * 填充异常轨迹 
233       */  
234      public synchronized native Throwable fillInStackTrace();  
235  
236      /** 
237       * 返回当前的异常轨迹的拷贝 
238       */  
239      public StackTraceElement[] getStackTrace() {  
240          return (StackTraceElement[]) getOurStackTrace().clone();  
241      }  
242  
243      
244      /** 
245       * 获取当前的异常轨迹 
246        */  
247      private synchronized StackTraceElement[] getOurStackTrace() {  
248         //如果第一次调用此方法则初始化异常轨迹数组  
249          if (stackTrace == null) {  
250            //获得异常轨迹深度  
251              int depth = getStackTraceDepth();  
252            //创建新的异常轨迹数组,并填充它  
253              stackTrace = new StackTraceElement[depth];  
254              
255            for (int i=0; i < depth; i++)  
256                stackTrace[i] = getStackTraceElement(i);//获取指定位标的异常轨迹  
257          }  
258          
259          return stackTrace;  
260      }  
261  
262      /** 
263       * 设置异常轨迹 
264       */  
265      public void setStackTrace(StackTraceElement[] stackTrace) {  
266         //拷贝设置参数  
267          StackTraceElement[] defensiveCopy =  
268              (StackTraceElement[]) stackTrace.clone();  
269          
270         //如果设置参数有空元素则抛出异常  
271          for (int i = 0; i < defensiveCopy.length; i++)  
272              if (defensiveCopy[i] == null)  
273                  throw new NullPointerException("stackTrace[" + i + "]");  
274  
275         //设置当前对象的异常轨迹  
276          this.stackTrace = defensiveCopy;  
277      }  
278  
279      /** 
280       * 异常轨迹的深度,0表示无法获得 
281       */  
282      private native int getStackTraceDepth();  
283  
284      /** 
285       * 获取指定位标的异常轨迹 
286       */  
287      private native StackTraceElement getStackTraceElement(int index);  
288  
289      
290      private synchronized void writeObject(java.io.ObjectOutputStream s)  
291          throws IOException  
292      {  
293          getOurStackTrace();  
294          s.defaultWriteObject();  
295      }  
296}  
原文地址:https://www.cnblogs.com/hupp/p/4623090.html