第四章 异常
4.1异常的简介
1、含义:Java程序在编译或者运行过程中出现的错误。是对问题的描述,将问题进行对象的封装。
2、由来:问题也是现实生活中的一个具体事物,也可以通过java的类的形式进行描述,并封装成对象。
3、分类
⑴、异常的体系
⑵、分类
①、Error类:对于Error一般不写针对性的代码对其进行处理
②、Exception类:对于Exception类可以使用针对性的代码对其进行处。Exception类是程序能够捕获到的异常情况。它又可以分为两大类:
A、运行时异常(为RuntimeException)是一种设计或者是实现问题上出现的错误,大多数是由于程序设计不当而引发的,但这种错误要在运行期间才会发生和被发现
B、编译时被检测异常:该异常在编译时,如果没有处理,编译失败,该异常被标,代表可以被处理
4.2异常的处理
1、方式
⑴、try{
需要被检测的代码;
}catch(异常类变量){
处理方式;
}finally{
一定会执行的语句;
通常用于关闭资源。比如数据库操作
只有一种情况finally不会执行,当执行到System.exit(0)时。因为jvm已经退出了
}
⑵、throws:在方法上
2、对多异常的处理
⑴、声明异常时,建议声明更为具体,这样处理也具体。建议一定要具体处理,
⑵、声明几个异常就对应有几个catch块,不要定义多余的catch块,如果多个catch块中的异常出现继承时,父类的catch块放最后。
3、对捕获到的异常对象进行处理的常见方法操作
⑴、getMessage方法
⑵、toString方法
⑶、printStackTrace方法
4、异常的处理方式的格式
⑴、try{
需要被检测的代码;
}catch(异常类 变量){
处理方式;
}finally{
一定会执行的语句;
}
⑵、try{
需要被检测的代码;
}catch(异常类 变量){
处理方式;
⑶、try{
需要被检测的代码;
}finally{
一定会执行的语句;
}
5、异常在子父类覆盖中的体现:
⑴、如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类
⑵、如果父类抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集
⑶、如果父类或者接口的方法中没有异常抛出,那么子类再覆盖方法时,也不可以抛出异常,如果子类方法发生了异常,就必须进行try处理,绝对不能抛出。
6、异常的好处:
⑴、将问题进行封装
⑵、将正常流程代码和问题处理代码相分离,方便于阅读。
7、代码示例
class Demo1{
//在功能上通过throws的关键字声明了该功能有可能会出现问题
double div1(double a,double b) throws ArithmeticException, ArrayIndexOutOfBoundsException{
int[]arr = newint[(int) a];
Sop(arr[2]);
return a/b;
}
intdiv(int a,int b) { //throws Exception 在功能上通过throws的关键字声明了
return a/b;//报出ArithmeticException错误
}
}
publicclass AboutException {
publicstaticvoidmain(String[] args){ //throwsArithmeticException
Demo1 d = new Demo1();
double i = d.div1(3.0, 0.0);
try{
int x= d.div(4, 0);
Sop("x="+x);
}catch(ArithmeticException e){
//相当于Exception e = new ArithmeticException();
Sop("除零了");
Sop(e.getMessage());//打印异常信息
Sop(e.toString());//打印的是 异常名称:异常信息
e.printStackTrace();//打印的是 异常名称:异常信息,异常出现的位置。
//其实jvm默认的异常处理机制就是printStackTrace方法
}catch(ArrayIndexOutOfBoundsException e){
Sop(e.toString());
Sop("角标越界了");
}finally{
}
Sop("over");
}
}
4.3 自定义异常
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{
privateintvalue;
FuShuException(){
super();
}
FuShuException(String message,int value){
super(message);
this.value = value;
}
publicint getValue() {
returnvalue;
}
}
class Demo2{
intdiv(int a,int b) //throws FuShuException:报错的原因
{ if(b<0)
thrownewFuShuException("除数出现负数的情况",b);
//手动通过throw关键字抛出一个自定义异常对象
return a/b;
}
}
publicclassUserDefinedExceptions {
publicstaticvoidmain(String[] args) {
Demo2 d = new Demo2();
try {
int i = d.div(3, -1);
Sop("i="+i);
} catch (FuShuException e) {
Sop(e.toString());
Sop("除数出现负数是"+e.getValue());
}
Sop("over");
}
}