2023年11月29日发(作者:)

解析Java中所有错误和异常的⽗类ble

这篇⽂章主要介绍了Java中所有错误和异常的⽗类ble,⽂章中简单地分析了其源码,说明在代码注释中,需要的朋友可以参考下

java语⾔中,错误类的基类是,异常类的基类是ion

1)相同点:ion都是ble的⼦类,因此ion⾃⾝及其⼦类都可以作为throw

使⽤对象,如:throw new MyError();throw new MyException();其中,MyError类是的⼦类,MyException类是ion的⼦类。

2)不同点:⾃⾝及其⼦类不需要try-catch语句的⽀持,可在任何时候将返回⽅法,如下⾯的⽅法定义:

public String myMethod() {

throw new MyError();

}

其中MyError类是类的⼦类。

ion⾃⾝及其⼦类需要try-catch语句的⽀持,如下的⽅法定义是错误的:

public String myMethod() {

throw new MyException();

}

正确的⽅法定义如下:

public String myMethod() throws MyException {

throw new MyException();

}

其中MyException类是ion的⼦类。

JAVA异常是在java程序运⾏的时候遇到⾮正常的情况⽽创建的对象,它封装了异常信息,java异常的根类为ble,整个类有两个

直接⼦类是程序本⾝⽆法恢复的严重错误.Exception则表⽰可以被程序捕获并处理的异常错

.JVM⽤⽅法调⽤栈来跟踪每个线程中⼀系列的⽅法调⽤过程,该栈保存了每个调⽤⽅法的本地信息.对于独⽴的JAVA程序,可以⼀直到该程

序的main⽅法.当⼀个新⽅法被调⽤的时候,JVM把描述该⽅法的栈结构置⼊栈顶,位于栈顶的⽅法为正确执⾏的⽅法.当⼀个JAVA⽅法正常执

⾏完毕,JVM回从调⽤栈中弹处该⽅法的栈结构,然后继续处理前⼀个⽅法.如果java⽅法在执⾏代码的过程中抛出异常,JVM必须找到能捕获异

常的catch块代码.它⾸先查看当前⽅法是否存在这样的catch代码块,如果存在就执⾏该 catch代码块,否则JVM回调⽤栈中弹处该⽅法的栈结

,继续到前⼀个⽅法中查找合适的catch代码块.最后如果JVM向上追到了main()⽅法,也就是⼀直把异常抛给了main()⽅法,仍然没有找到该异

常处理的代码块,该线程就会异常终⽌,如果该线程是主线程,应⽤程序也随之终⽌,此时 JVM将把异常直接抛给⽤户,在⽤户终端上会看到原始

的异常信息.

ble源代码解析

package ;

import .*;

/**

*

* Throwable是所有ErrorExceptiong的⽗类

* 注意它有四个构造函数:

* Throwable()

* Throwable(String message)

* Throwable(Throwable cause)

* Throwable(String message, Throwable cause)

*

*/

public class Throwable implements Serializable {

private static final long serialVersionUID = -3047285L;

/**

* Native code saves some indication of the stack backtrace in this slot.

* 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 String getLocalizedMessage() {

return getMessage();

}

/**

* 获取起因对象

*/

public Throwable getCause() {

return (cause==this ? null : cause);

}

/**

* 初始化起因对象,这个⽅法只能在未被初始化的情况下调⽤⼀次

*/

if (ourCause != null)

tackTraceAsCause(s, trace);

}

}

/**

* 打印起因对象的信息

* @param s 打印的流

* @param causedTrace 有此对象引起的异常的异常轨迹

*/

private void printStackTraceAsCause(PrintStream s,

StackTraceElement[] causedTrace)

{

//获得当前的异常轨迹

StackTraceElement[] trace = getOurStackTrace();

//m为当前异常轨迹数组的最后⼀个元素位置,

//n为当前对象引起的异常的异常轨迹数组的最后⼀个元素

int m = -1, n = -1;

//分别从两个数组的后⾯做循环,如果相等则⼀直循环,直到不等或数组到头

while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {

m--; n--;

}

StackTraceElement[] trace = getOurStackTrace();

int m = -1, n = -1;

while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) {

m--; n--;

}

int framesInCommon = - 1 - m;

n("Caused by: " + this);

for (int i=0; i <= m; i++)

n("tat " + trace[i]);

if (framesInCommon != 0)

n("t... " + framesInCommon + " more");

// Recurse if we have a cause

Throwable ourCause = getCause();

if (ourCause != null)

}

/**

* 异常轨迹的深度,0表⽰⽆法获得

*/

private native int getStackTraceDepth();

/**

* 获取指定位标的异常轨迹

*/

private native StackTraceElement getStackTraceElement(int index);

private synchronized void writeObject(OutputStream s)

throws IOException

{

getOurStackTrace();

tWriteObject();

}

}

以下讲述的是平时遇到的,⽐较常见的具体异常情况,跟上⾯有部分重复:

Throwable是所有异常的根,ble

Error是错误,

Exception是异常,ion

Throwable 有两个重要的⼦类:Exception(异常)和 Error(错误),⼆者都是 Java 异常处理的重要⼦类,各⾃都包含⼤量⼦类。

Error(错误):是程序⽆法处理的错误,表⽰运⾏应⽤程序中较严重问题。⼤多数错误与代码编写者执⾏的操作⽆关,⽽表⽰代码运⾏时

JVMJava 虚拟机)出现的问题。例如,Java虚拟机运⾏错误(Virtual MachineError),当 JVM 不再有继续执⾏操作所需的内存资源时,

将出现 OutOfMemoryError。这些异常发⽣时,Java虚拟机(JVM)⼀般会选择线程终⽌。

这些错误表⽰故障发⽣于虚拟机⾃⾝、或者发⽣在虚拟机试图执⾏应⽤时,如Java虚拟机运⾏错误(Virtual MachineError)、类定义错误

NoClassDefFoundError)等。这些错误是不可查的,因为它们在应⽤程序的控制和处理能⼒之 外,⽽且绝⼤多数是程序运⾏时不允许出

现的状况。对于设计合理的应⽤程序来说,即使确实发⽣了错误,本质上也不应该试图去处理它所引起的异常状况。在 Java中,错误通过

Error的⼦类描述。

Exception(异常):是程序本⾝可以处理的异常。

Exception 类有⼀个重要的⼦类 RuntimeExceptionRuntimeException 类及其⼦类表⽰“JVM 常⽤操作引发的错误。例如,若试图使⽤空

值对象引⽤、除数为零或数组越界,则分别引发运⾏时异常(NullPointerExceptionArithmeticException)和

ArrayIndexOutOfBoundException

注意:异常和错误的区别:异常能被程序本⾝可以处理,错误是⽆法处理。

⼆、Exception

⼀般分为Checked异常和Runtime异常,所有RuntimeException类及其⼦类的实例被称为Runtime异常,不属于该范畴的异常则被称为

CheckedException

Checked异常

只有java语⾔提供了Checked异常,Java认为Checked异常都是可以被处理的异常,所以Java程序必须显⽰处理Checked异常。如果程序没

有处理Checked异常,该程序在编译时就会发⽣错误⽆法编译。这体现了Java的设计哲学:没有完善错误处理的代码根本没有机会被执⾏。

Checked异常处理⽅法有两种

1 当前⽅法知道如何处理该异常,则⽤atch块来处理该异常。

2 当前⽅法不知道如何处理,则在定义该⽅法是声明抛出该异常。

package ;

import ption;

import ption;

/**

* Checked异常测试⽅法

* @author xy

*

*/

public class CheckedExceptionMethods

{

// 总异常类,既有checkedException⼜有RuntimeException,所以其中的checkedException必须处理

public void method1() throws Exception

{

n("我是抛出异常总类的⽅法");

}

// 捕获并处理这个异常

public void testMethod1_01()

{

try

tackTrace();

}

}

public void testMethod2_02() throws Exception

{

method2();

}

}

我们⽐较熟悉的Checked异常有

otFoundException

MetodException

ption

RuntimeException

Runtime如除数是0和数组下标越界等,其产⽣频繁,处理⿇烦,若显⽰申明或者捕获将会对程序的可读性和运⾏效率影响很⼤。所以由系

统⾃动检测并将它们交给缺省的异常处理程序。当然如果你有处理要求也可以显⽰捕获它们。

package ;

/**