JAVA編程——Throwable常見異常及源碼詳解

<span style="font-family:Microsoft YaHei;font-size:14px;"><span lang="EN-US">Throwable</span>是<span lang="EN-US">java.lang</span>包中一個專門用來處理異常的類。它有兩個子類,即<span lang="EN-US">Error </span>和<span lang="EN-US">Exception</span>,它們分別用來處理兩組異常。</span><span style="font-family:Microsoft YaHei;font-size:14px;">
</span>
<span style="font-family:Microsoft YaHei;font-size:12px;"><span lang="EN-US">Error</span>用來處理程序運行環境方面的異常,這類異常主要是和硬件有關的,而不是由程序本身拋出的。<span lang="EN-US"> 
Exception</span>是<span lang="EN-US">Throwable</span>的一個主要子類。                                                                                                                                                                           <span style="white-space:pre">	</span></span><span style="font-family:Microsoft YaHei;font-size:12px;"><span lang="EN-US">Exception</span>下面還有子類,其中一部分子類分別對應於<span lang="EN-US">Java</span>程序運行時常常遇到的各種異常的處理,其中包括隱式異常。<span>							</span><span lang="EN-US">Exception </span>子類下面的另一部分子類對應於<span lang="EN-US">Java</span>程序中的非運行時異常的處理(在下圖中將它們直接屬於<span lang="EN-US">Exception</span>了),這些異常也稱爲顯式異常。它們都<span style="white-space:pre">	</span>是在程序中用語句拋出、並且也是用語句進行捕獲的。</span><span lang="EN-US" style="font-family: Arial, Helvetica, sans-serif;"><span style="font-family:Microsoft YaHei;font-size:12px;"> </span></span>
<span lang="EN-US"><span style="font-family:Microsoft YaHei;"><span style="font-size:12px;">
</span></span><span style="font-family:Microsoft YaHei;font-size:12px;">    </span></span><span style="font-family:Microsoft YaHei;font-size:12px;">一些主要子類對應的異常處理功能簡要說明如下:<span lang="EN-US"> 
    ArithmeticException——</span>由於除數爲0引起的異常;<span lang="EN-US"> 
    ArrayStoreException——</span>由於數組存儲空間不夠引起的異常;<span lang="EN-US"> 
    ClassCastException—</span>一當把一個對象歸爲某個類,但實際上此對象並不是由這個類 創建的,也不是其子類創建的,則會引起異常;<span lang="EN-US"> 
    IllegalMonitorStateException——</span>監控器狀態出錯引起的異常;<span lang="EN-US"> 
    NegativeArraySizeException—</span>一數組長度是負數,則產生異常;<span lang="EN-US"> 
    NullPointerException—</span>一程序試圖訪問一個空的數組中的元素或訪問空的對象中的 方法或變量時產生異常;<span lang="EN-US"> 
    OutofMemoryException——</span>用<span lang="EN-US">new</span>語句創建對象時,如系統無法爲其分配內存空間則產生異常;<span lang="EN-US"> 
    SecurityException——</span>由於訪問了不應訪問的指針,使安全性出問題而引起異常;<span lang="EN-US"> 
    IndexOutOfBoundsExcention——</span>由於數組下標越界或字符串訪問越界引起異常;<span lang="EN-US"> 
    IOException——</span>由於文件未找到、未打開或者<span lang="EN-US">I/O</span>操作不能進行而引起異常;<span lang="EN-US"> 
    ClassNotFoundException——</span>未找到指定名字的類或接口引起異常;<span lang="EN-US"> 
    CloneNotSupportedException——</span>一程序中的一個對象引用<span lang="EN-US">Object</span>類的<span lang="EN-US">clone</span>方法,但 此對象並沒有連接<span lang="EN-US">Cloneable</span>接口,從而引起異常;<span lang="EN-US"> 
    InterruptedException—</span>一當一個線程處於等待狀態時,另一個線程中斷此線程,從 而引起異常,有關線程的內容,將在下一章講述;<span lang="EN-US"> 
    NoSuchMethodException</span>一所調用的方法未找到,引起異常;<span lang="EN-US"> 
    Illega1AccessExcePtion—</span>一試圖訪問一個非<span lang="EN-US">public</span>方法;<span lang="EN-US"> 
    StringIndexOutOfBoundsException——</span>訪問字符串序號越界,引起異常;<span lang="EN-US"> 
    ArrayIdexOutOfBoundsException—</span>一訪問數組元素下標越界,引起異常;<span lang="EN-US"> 
    NumberFormatException——</span>字符的<span lang="EN-US">UTF</span>代碼數據格式有錯引起異常;<span lang="EN-US"> 
    IllegalThreadException—</span>一線程調用某個方法而所處狀態不適當,引起異常;<span lang="EN-US"> 
    FileNotFoundException——</span>未找到指定文件引起異常;<span lang="EN-US"> 
    EOFException——</span>未完成輸入操作即遇文件結束引起異常。</span><span style="font-family:Microsoft YaHei;font-size:14px;">
</span>
<span style="font-family:Microsoft YaHei;font-size:14px;">源碼解析:</span>
<span style="font-family:Microsoft YaHei;font-size:14px;">	package java.lang;  
	import java.io.*;  
	/** 
	*  
	* Throwable是所有Error和Exceptiong的父類 
	* 注意它有四個構造函數: 
	* Throwable() 
	* Throwable(String message) 
	* Throwable(Throwable cause) 
	* Throwable(String message, Throwable cause) 
	*  
	*/  
	public class Throwable implements Serializable {  
	      private static final long serialVersionUID = -3042686055658047285L;  
	  
	      /** 
	       * Native code saves some indication of the stack backtrace in this slot. 
	       */  
	      private transient Object backtrace;   
	  
	      /** 
	       * 描述此異常的信息 
	       */  
	      private String detailMessage;  
	  
	      /** 
	       * 表示當前異常由那個Throwable引起 
	        * 如果爲null表示此異常不是由其他Throwable引起的 
	        * 如果此對象與自己相同,表明此異常的起因對象還沒有被初始化 
	       */  
	      private Throwable cause = this;  
	  
	      /** 
	       * 描述異常軌跡的數組 
	       */  
	      private StackTraceElement[] stackTrace;  
	  
	      /** 
	       * 構造函數,起因對象沒有被初始化可以在以後使用initCause進行初始化 
	        * fillInStackTrace可以用來初始化它的異常軌跡的數組 
	       */  
	      public Throwable() {  
	          fillInStackTrace();  
	      }  
	  
	      /** 
	       * 構造函數 
	       */  
	      public Throwable(String message) {  
	         //填充異常軌跡數組  
	          fillInStackTrace();  
	         //初始化異常描述信息  
	          detailMessage = message;  
	      }  
	  
	      /** 
	       * 構造函數,cause表示起因對象 
	       */  
	      public Throwable(String message, Throwable cause) {  
	          fillInStackTrace();  
	          detailMessage = message;  
	          this.cause = cause;  
	      }  
	  
	      /** 
	       * 構造函數 
	       */  
	      public Throwable(Throwable cause) {  
	          fillInStackTrace();  
	          detailMessage = (cause==null ? null : cause.toString());  
	          this.cause = cause;  
	      }  
	  
	      /** 
	       * 獲取詳細信息 
	       */  
	      public String getMessage() {  
	          return detailMessage;  
	      }  
	  
	      /** 
	       * 獲取詳細信息 
	       */  
	      public String getLocalizedMessage() {  
	          return getMessage();  
	      }  
	  
	      /** 
	       * 獲取起因對象 
	       */  
	      public Throwable getCause() {  
	          return (cause==this ? null : cause);  
	      }  
	  
	      /** 
	       * 初始化起因對象,這個方法只能在未被初始化的情況下調用一次 
	       */  
	      public synchronized Throwable initCause(Throwable cause) {  
	         //如果不是未初始化狀態則拋出異常  
	          if (this.cause != this)  
	              throw new IllegalStateException("Can't overwrite cause");  
	          
	        //要設置的起因對象與自身相等則拋出異常  
	          if (cause == this)  
	              throw new IllegalArgumentException("Self-causation not permitted");  
	          
	         //設置起因對象  
	          this.cause = cause;  
	         //返回設置的起因的對象  
	          return this;  
	      }  
	  
	      /** 
	       * 字符串表示形式 
	       */  
	      public String toString() {       
	          String s = getClass().getName();          
	          String message = getLocalizedMessage();        
	          return (message != null) ? (s + ": " + message) : s;  
	      }  
	  
	      /** 
	       * 打印出錯誤軌跡 
	       */  
	      public void printStackTrace() {   
	          printStackTrace(System.err);  
	      }  
	  
	      /** 
	       * 打印出錯誤軌跡 
	       */  
	      public void printStackTrace(PrintStream s) {  
	          synchronized (s) {  
	            //調用當前對象的toString方法  
	              s.println(this);  
	            //獲取異常軌跡數組  
	              StackTraceElement[] trace = getOurStackTrace();  
	              
	            //打印出每個元素的字符串表示  
	              for (int i=0; i < trace.length; i++)  
	                s.println("\tat " + trace[i]);  
	  
	            //獲取起因對象  
	              Throwable ourCause = getCause();  
	              
	            //遞歸的打印出起因對象的信息  
	              if (ourCause != null)  
	                ourCause.printStackTraceAsCause(s, trace);  
	          }  
	      }  
	  
	      /** 
	       * 打印起因對象的信息 
	       * @param s 打印的流 
	        * @param causedTrace 有此對象引起的異常的異常軌跡  
	       */  
	      private void printStackTraceAsCause(PrintStream s,  
	                                          StackTraceElement[] causedTrace)  
	      {  
	         //獲得當前的異常軌跡  
	          StackTraceElement[] trace = getOurStackTrace();  
	         //m爲當前異常軌跡數組的最後一個元素位置,   
	         //n爲當前對象引起的異常的異常軌跡數組的最後一個元素  
	          int m = trace.length-1, n = causedTrace.length-1;  
	         //分別從兩個數組的後面做循環,如果相等則一直循環,直到不等或數組到頭  
	          while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {  
	              m--; n--;  
	         }  
	          
	         //相同的個數  
	          int framesInCommon = trace.length - 1 - m;  
	          
	         //打印出不同的錯誤軌跡  
	          s.println("Caused by: " + this);  
	          for (int i=0; i <= m; i++)  
	              s.println("\tat " + trace[i]);  
	          //如果有相同的則打印出相同的個數  
	          if (framesInCommon != 0)  
	              s.println("\t... " + framesInCommon + " more");  
	  
	         //獲得此對象的起因對象,並遞歸打印出信息  
	          Throwable ourCause = getCause();  
	          if (ourCause != null)  
	              ourCause.printStackTraceAsCause(s, trace);  
	      }  
	  
	      /** 
	       * 打印出錯誤軌跡 
	       */  
	      public void printStackTrace(PrintWriter s) {   
	          synchronized (s) {  
	              s.println(this);  
	              StackTraceElement[] trace = getOurStackTrace();  
	              for (int i=0; i < trace.length; i++)  
	                  s.println("\tat " + trace[i]);  
	  
	              Throwable ourCause = getCause();  
	              if (ourCause != null)  
	                  ourCause.printStackTraceAsCause(s, trace);  
	          }  
	      }  
	  
	      /** 
	       * 打印起因對象的信息 
	        */  
	      private void printStackTraceAsCause(PrintWriter s,  
	                                          StackTraceElement[] causedTrace)  
	      {  
	          // assert Thread.holdsLock(s);  
	  
	          // Compute number of frames in common between this and caused  
	          StackTraceElement[] trace = getOurStackTrace();  
	          int m = trace.length-1, n = causedTrace.length-1;  
	          while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {  
	              m--; n--;  
	          }  
	          int framesInCommon = trace.length - 1 - m;  
	  
	          s.println("Caused by: " + this);  
	          for (int i=0; i <= m; i++)  
	              s.println("\tat " + trace[i]);  
	          if (framesInCommon != 0)  
	              s.println("\t... " + framesInCommon + " more");  
	  
	          // Recurse if we have a cause  
	          Throwable ourCause = getCause();  
          if (ourCause != null)  
	              ourCause.printStackTraceAsCause(s, trace);  
	      }  
	  
	      /** 
	       * 填充異常軌跡 
	       */  
	      public synchronized native Throwable fillInStackTrace();  
	  
	      /** 
	       * 返回當前的異常軌跡的拷貝 
	       */  
	      public StackTraceElement[] getStackTrace() {  
	          return (StackTraceElement[]) getOurStackTrace().clone();  
	      }  
	  
	      
	      /** 
	       * 獲取當前的異常軌跡 
	        */  
      private synchronized StackTraceElement[] getOurStackTrace() {  
	         //如果第一次調用此方法則初始化異常軌跡數組  
	          if (stackTrace == null) {  
	            //獲得異常軌跡深度  
	              int depth = getStackTraceDepth();  
	            //創建新的異常軌跡數組,並填充它  
	              stackTrace = new StackTraceElement[depth];  
	              
	            for (int i=0; i < depth; i++)  
	                stackTrace[i] = getStackTraceElement(i);//獲取指定位標的異常軌跡  
	          }  
	          
	          return stackTrace;  
	      }  
	  
	      /** 
	       * 設置異常軌跡 
	       */  
	      public void setStackTrace(StackTraceElement[] stackTrace) {  
	         //拷貝設置參數  
	          StackTraceElement[] defensiveCopy =  
	              (StackTraceElement[]) stackTrace.clone();  
	          
	         //如果設置參數有空元素則拋出異常  
	          for (int i = 0; i < defensiveCopy.length; i++)  
	              if (defensiveCopy[i] == null)  
	                  throw new NullPointerException("stackTrace[" + i + "]");  
	  
	         //設置當前對象的異常軌跡  
	          this.stackTrace = defensiveCopy;  
	      }  
	  
	      /** 
	       * 異常軌跡的深度,0表示無法獲得 
	       */  
	      private native int getStackTraceDepth();  
	  
	      /** 
	       * 獲取指定位標的異常軌跡 
	       */  
	      private native StackTraceElement getStackTraceElement(int index);  
	  
	      
	      private synchronized void writeObject(java.io.ObjectOutputStream s)  
	          throws IOException  
	      {  
	          getOurStackTrace();  
	          s.defaultWriteObject();  
	      }  
	}  
</span>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章