在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.*;
public class Throwable implements Serializable {
private static final long serialVersionUID = -3042686055658047285L;
private transient Object backtrace;
private String detailMessage;
private Throwable cause = this;
private StackTraceElement[] stackTrace;
public Throwable() {
fillInStackTrace();
}
public Throwable(String message) {
//填充异常轨迹数组
fillInStackTrace();
//初始化异常描述信息
detailMessage = message;
}
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);
}
}
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;
}
private native int getStackTraceDepth();
private native StackTraceElement getStackTraceElement(int index);
private synchronized void writeObject(java.io.ObjectOutputStream s)
throws IOException
{
getOurStackTrace();
s.defaultWriteObject();
}
}



