解析Java中所有錯誤和異常的父類java.lang.Throwable_java

來源:互聯網
上載者:User

在java語言中,錯誤類的基類是java.lang.Error,異常類的基類是java.lang.Exception。
1)相同點:java.lang.Error和java.lang.Exception都是java.lang.Throwable的子類,因此java.lang.Error和java.lang.Exception自身及其子類都可以作為throw的使用對象,如:throw new MyError();和throw new MyException();其中,MyError類是java.lang.Error的子類,MyException類是java.lang.Exception的子類。
2)不同點:java.lang.Error自身及其子類不需要try-catch語句的支援,可在任何時候將返回方法,如下面的方法定義:

public String myMethod() { throw new MyError(); } 

其中MyError類是java.lang.Error類的子類。
java.lang.Exception自身及其子類需要try-catch語句的支援,如下的方法定義是錯誤的:

public String myMethod() { throw new MyException(); } 

正確的方法定義如下:

public String myMethod() throws MyException { throw new MyException(); } 

其中MyException類是java.lang.Exception的子類。

JAVA異常是在java程式啟動並執行時候遇到非正常的情況而建立的對象,它封裝了異常資訊,java異常的根類為java.lang.Throwable,整個類有兩個直接子類java.lang.Error和java.lang.Exception.Error是程式本身無法恢複的嚴重錯誤.Exception則表示可以被程式捕獲並處理的異常錯誤.JVM用方法調用棧來跟蹤每個線程中一系列的方法調用過程,該棧儲存了每個調用方法的本地資訊.對於獨立的JAVA程式,可以一直到該程式的main方法.當一個新方法被調用的時候,JVM把描述該方法的棧結構置入棧頂,位於棧頂的方法為正確執行的方法.當一個JAVA方法正常執行完畢,JVM回從調用棧中彈處該方法的棧結構,然後繼續處理前一個方法.如果java方法在執行代碼的過程中拋出異常,JVM必須找到能捕獲異常的catch塊代碼.它首先查看當前方法是否存在這樣的catch代碼塊,如果存在就執行該 catch代碼塊,否則JVM回調用棧中彈處該方法的棧結構,繼續到前一個方法中尋找合適的catch代碼塊.最後如果JVM向上追到了main()方法,也就是一直把異常拋給了main()方法,仍然沒有找到該異常處理的代碼塊,該線程就會異常終止,如果該線程是主線程,應用程式也隨之終止,此時 JVM將把異常直接拋給使用者,在使用者終端上會看到原始的異常資訊.

Java.lang.throwable原始碼解析

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();   } } 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.