zoukankan      html  css  js  c++  java
  • 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}  
  • 相关阅读:
    C++ std::map::erase用法及其陷阱
    写在分类之首-----to do list!
    Gradle系列教材(译)
    Android进阶-UIL分析
    ArrayList源码解析
    Android进阶-MVP
    高质量代码-树的子结构
    高质量代码-并和链表
    高质量代码-翻转链表
    高质量代码-链表中倒数第k个结点
  • 原文地址:https://www.cnblogs.com/hupp/p/4623090.html
Copyright © 2011-2022 走看看