<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>