企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] # 异常 ## 异常的继承体系 在Java中使用Exception类来描述异常 ![](https://box.kancloud.cn/4bf432662bdb66cb44a28951718e2c5a_2014x226.jpg) Exception 类及其子类是 Throwable 的一种形式,它用来表示java程序中可能会产生的异常,并要求对产生的异常进行合理的异常处理。 我们可以发现Exception有继承关系,它的父类是Throwable。Throwable是Java 语言中所有错误或异常的超类。 ![](https://box.kancloud.cn/0ecbf069fcb4f92eb7e0bd0304895dae_1460x568.jpg) 另外,在异常Exception类中,有一个子类要特殊说明一下,RuntimeException子类,RuntimeException及其它的子类只能在Java程序运行过程中出现 异常继承体系总结: Throwable: 它是所有错误与异常的超类(祖宗类) |- Error 错误 |- Exception 编译期异常,进行编译JAVA程序时出现的问题 |- RuntimeException 运行期异常, JAVA程序运行过程中出现的问题 ## 抛出异常throw 在java中,提供了一个throw关键字,它用来抛出一个指定的异常对象。那么,抛出一个异常具体如何操作呢? * 1,创建一个异常对象。封装一些提示信息(信息可以自己编写)。 * 2,需要将这个异常对象告知给调用者。怎么告知呢?怎么将这个异常对象传递到调用者处呢?通过关键字throw就可以完成。throw 异常对象; throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。 使用格式: ~~~ throw new 异常类名(参数); ~~~ 例如: ~~~ throw new NullPointerException("要访问的arr数组不存在"); throw new ArrayIndexOutOfBoundsException("该索引在数组中不存在,已超出范围"); ~~~ * 下面是异常类ArrayIndexOutOfBoundsException与NullPointerException的构造方法 ![](https://box.kancloud.cn/52e4aa4bd1711d65b450bcb439ac3c17_2054x760.jpg) ## 声明异常throws 声明:将问题标识出来,报告给调用者。如果方法内通过throw抛出了编译时异常,而没有捕获处理(稍后讲解该方式),那么必须通过throws进行声明,让调用者去处理。 声明异常格式: ~~~ 修饰符 返回值类型 方法名(参数) throws 异常类名1,异常类名2… { } ~~~ ## 捕获异常try…catch…finally 捕获:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行指定方式的处理 捕获异常格式: ~~~ try { //需要被检测的语句。 } catch(异常类 变量) { //参数。 //异常的处理语句。 } finally { //一定会被执行的语句。 } ~~~ try:该代码块中编写可能产生异常的代码。 catch:用来进行某种异常的捕获,实现对捕获到的异常进行处理。 finally:有一些特定的代码无论异常是否发生,都需要执行。另外,因为异常会引发程序跳转,导致有些语句执行不到。而finally就是解决这个问题的,在finally代码块中存放的代码都是一定会被执行的。 ## 运行时期异常 * RuntimeException和他的所有子类异常,都属于运行时期异常。NullPointerException,ArrayIndexOutOfBoundsException等都属于运行时期异常. * 运行时期异常的特点: * 方法中抛出运行时期异常,方法定义中无需throws声明,调用者也无需处理此异常 * 运行时期异常一旦发生,需要程序人员修改源代码. ## 异常在方法重写中细节 * 子类覆盖父类方法时,如果父类的方法声明异常,子类只能声明父类异常或者该异常的子类,或者不声明。 例如: ~~~ class Fu { public void method () throws RuntimeException { } } class Zi extends Fu { public void method() throws RuntimeException { } //抛出父类一样的异常 //public void method() throws NullPointerException{ } //抛出父类子异常 } ~~~ * 当父类方法声明多个异常时,子类覆盖时只能声明多个异常的子集。 例如: ~~~ class Fu { public void method () throws NullPointerException, ClassCastException{ } } class Zi extends Fu { public void method()throws NullPointerException, ClassCastException { } public void method() throws NullPointerException{ } //抛出父类异常中的一部分 public void method() throws ClassCastException { } //抛出父类异常中的一部分 } ~~~ * 当被覆盖的方法没有异常声明时,子类覆盖时无法声明异常的。 例如: ~~~ class Fu { public void method (){ } } class Zi extends Fu { public void method() throws Exception { }//错误的方式 } ~~~ 举例:父类中会存在下列这种情况,接口也有这种情况 问题:接口中没有声明异常,而实现的子类覆盖方法时发生了异常,怎么办? 答:无法进行throws声明,只能catch的捕获。万一问题处理不了呢?catch中继续throw抛出,但是只能将异常转换成RuntimeException子类抛出 ~~~ interface Inter { public abstract void method(); } class Zi implements Inter { public void method(){ //无法声明 throws Exception int[] arr = null; if (arr == null) { //只能捕获处理 try{ throw new Exception(“哥们,你定义的数组arr是空的!”); } catch(Exception e){ System.out.println(“父方法中没有异常抛出,子类中不能抛出Exception异常”); //我们把异常对象e,采用RuntimeException异常方式抛出 throw new RuntimeException(e); } } } } ~~~ ## 异常中常用方法 在Throwable类中为我们提供了很多操作异常对象的方法,常用的如下 ![](https://box.kancloud.cn/faf01dc4ebfcc028440ea16fed81fae0_1636x486.jpg) * getMessage方法:返回该异常的详细信息字符串,即异常提示信息 * toString方法:返回该异常的名称与详细信息字符串 * printStackTrace:在控制台输出该异常的名称与详细信息字符串、异常出现的代码位置 ~~~ try { Person p= null; if (p==null) { throw new NullPointerException(“出现空指针异常了,请检查对象是否为null”); } } catch (NullPointerException e) { String message = e.getMesage(); System.out.println(message ); String result = e.toString(); System.out.println(result); e.printStackTrace(); } ~~~ # 自定义异常 java中所有的异常类,都是继承Throwable,或者继承Throwable的子类。这样该异常才可以被throw抛出。 说明这个异常体系具备一个特有的特性:可抛性:即可以被throw关键字操作。 并且查阅异常子类源码,发现每个异常中都调用了父类的构造方法,把异常描述信息传递给了父类,让父类帮我们进行异常信息的封装。 例如NullPointerException异常类源代码: ~~~ public class NullPointerException extends RuntimeException { public NullPointerException() { super();//调用父类构造方法 } public NullPointerException(String s) { super(s);//调用父类具有异常信息的构造方法 } } ~~~ * 自定义异常继承Exception演示 ~~~ class MyException extends Exception{ /* 为什么要定义构造函数,因为看到Java中的异常描述类中有提供对异常对象的初始化方法。 */ public MyException(){ super(); } public MyException(String message) { super(message);// 如果自定义异常需要异常信息,可以通过调用父类的带有字符串参数的构造函数即可。 } } ~~~ * 自定义异常继承RuntimeException演示 ~~~ class MyException extends RuntimeException{ /* 为什么要定义构造函数,因为看到Java中的异常描述类中有提供对异常对象的初始化方法。 */ MyException(){ super(); } MyException(String message) { super(message);// 如果自定义异常需要异常信息,可以通过调用父类的带有字符串参数的构造函数即可。 } } ~~~