java中异常父类_解析Java中所有错误和异常的父类java.lang.Throwable

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

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值