第四章 异常
4.1异常的概要
4.1.1含义
Java程序在运行过程中出现的错误。是对问题的描述,将问题进行对象的封装。
4.1.2异常的由来
问题也是现实生活中的一个具体事物,也可以通过java的类的形式进行描述,并封装成对象。
4.1.3分类
1、异常的体系
2、分类
1)、Error类:对于Error一般不写针对性的代码对其进行处理
2)、Exception类:对于Exception类可以使用针对性的代码对其进行处。Exception类是程序能够捕获到的异常情况。它又可以分为两大类:
①运行时异常(为RuntimeException)是一种设计或者是实现问题上出现的错误,大多数是由于程序设计不当而引发的,但这种错误要在运行期间才会发生和被发现
②编译时被检测异常:该异常在编译时,如果没有处理,编译失败,该异常被标,代表可以被处理
4.1.4异常的处理
1、方式:
①、try{
需要被检测的代码;
}catch(异常类 变量){
处理方式;
}finally{
一定会执行的语句;
通常用于关闭资源。比如数据库操作
只有一种情况finally不会执行,当执行到System.exit(0)时。因为jvm已经退出了
}
②、throws:在函数上
2、对多异常的处理:
①、声明异常时,建议声明更为具体,这样处理也具体。建议一定要具体处理,
②、对方声明几个异常就对于有几个catch块,不要定义多余的catch块,如果多个catch块中的异常出现继承是,父类放最后。
3、对捕获到的异常对象进行处理的常见方法操作
①、getMessage方法
②、toString方法
③、printStackTrace方法
4、异常的处理方式的格式:
①、try{
需要被检测的代码;
}catch(异常类 变量){
处理方式;
}finally{
一定会执行的语句;
}
②、try{
需要被检测的代码;
}catch(异常类 变量){
处理方式;
③、try{
需要被检测的代码;
}finally{
一定会执行的语句;
}
5、异常在子父类覆盖中的体现:
①、子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类
②、如果父类抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集
③、如果父类或者接口的方法中没有异常抛出,那么子类再覆盖方法时,也不可以抛出异常,如果子类方法发生了异常,就必须进行try处理,绝对不能抛出
6、异常的好处:
①、将问题进行封装
②、将正常流程代码和问题处理代码相分离,方便于阅读。
7、代码示例
class Demo{ //在功能上通过throws的关键字声明了该功能有可能会出现问题 double div(double a,double b) throws ArithmeticException, ArrayIndexOutOfBoundsException { int[] arr = newint[(int) a]; System.out.println(arr[2]); return a/b; } //throws Exception 在功能上通过throws的关键字声明了 int div(int a,int b) { return a/b;//报出ArithmeticException错误 } } publicclass AboutException { publicstaticvoid main(String[] args){ //throws ArithmeticException Demo d = new Demo(); doublei = d.div1(3.0, 0.0); try{ int x = d.div(4, 0); System.out.println("x="+x); }catch(ArithmeticException e){ //相当于Exception e = new ArithmeticException(); System.out.println("除零了"); //打印异常信息 System.out.println(e.getMessage()); //打印的是异常名称:异常信息 System.out.println(e.toString()); //打印的是异常名称:异常信息,异常出现的位置。 e.printStackTrace(); //其实jvm默认的异常处理机制就是printStackTrace方法 }catch(ArrayIndexOutOfBoundsException e){ System.out.println(e.toString()); System.out.println("角标越界了"); }finally{ } System.out.println("over"); } }
4.2 自定义异常
1、原由: 因为项目中会出现特有的问题,而这些问题并未被java所描述并封装,所以对于这些特有问题进行自定义异常封装。
2、当在函数中出现throw抛出异常对象,那么就必须要给对于的处理动作,要么try,要么throws
3、如何定义异常信息?因为父类中已经把异常信息的操作都完成了,所以子类在构造时,通过 super
将异常信息传递给父类,这样就可以直接通过getMessage方法获取自定义的异常信息。
4、自定义异常:必须是自定义类继承Exception,其原因:异常类和异常对象都被抛出,他们都具备可抛性,他是Throwable这个体系中独有的,只有这个体系中的类和对象才可以被throw和throws操作。
5、throw和throws的区别
①、throw定义在函数中,throws用在函数上
②、throw抛出的是异常对象,throws抛出的是异常类,可以同时抛出多个,用逗号隔开。
注意:throw和return一样,单独存在时,是语句结束标志,后面的语句执行不到
6、RuntimeException
他是一个特殊的异常,如果在函数中抛出了异常,函数上不需要声明,之所以不需要声明,是因为不需要让调用者处理 ,如果函数上声明了异常,在函数中不需要处理自定义异常时,如果该异常的发生,无法继续运算,就让自定义异常继承RuntimeException
7、代码示例
class FuShuException extends RuntimeException{ private in tvalue; FuShuException(){ super(); } FuShuException(String message,int value){ super(message); this.value = value; } publicint getValue() { return value; } } class Demo{ //throws FuShuException:报错的原因{if(b<0) int div(int a,int b) thrownew FuShuException("除数出现负数的情况",b); //手动通过throw关键字抛出一个自定义异常对象 return a/b; } } publicclass UserDefinedExceptions { publicstaticvoid main(String[] args) { Demo d = new Demo(); try { int i = d.div(3, -1); System.out.println("i="+i); } catch (FuShuException e) { System.out.println(e.toString()); System.out.println("除数出现负数是"+e.getValue()); } System.out.println("over"); } }