java异常处理复习

一、先来看看Java异常类体系图

      java中通过类对所有的不正常的现象进行描述,并封装为对象。由这些类组成的一个专门处理Java中的各种异常的体系称为Java的异常体系。

     java的异常体系包含在java.lang这个包默认不需要导入。

     java异常体系

                    

如何判断一个错误与异常: 
  如果程序出现了不正常的信息,如果不正常的信息的类名是以Error结尾的,那么肯定是一个错误。 
  如果是以Exception结尾的,那么肯定就是一个异常。 

二、基本概念

(一)Throwable:异常和错误的基类,提供了错误堆栈实现等一系列方法。 两个直接子类:Error & Exception

(二)两个子类区别:

     1. Error: 程序不应该捕捉的错误,应该交由JVM来处理。一般可能指非常重大的错误。这个错误我们一般获取不到。

     2. Exception:程序中应该要捕获的错误。这个异常类及它的子类是我们需要学习获取的。

   (1)RuntimeException:运行期异常,是Exception的子类,但不需捕捉的异常超类,但是实际发生异常时,还是会蹦的,只是编译时没有报错而已。比如除数为零,数组空指针等等,这些都是在运行之后才会报错。

   (2)除了RuntimeException类和它的子类,其他类都被定义为Checked类,是需要显式处理可能出现的异常,否则编译就报错了。Checked类主要包含:IO类和SQL类的异常情况,这些在使用时经常要先显示处理异常(使用throws或try   catch捕获)。

三.java常见的异常(最好记住) 

(一)Exception 异常层次结构的根类

(二)ArithmeticException 算术错误情形,如以零作除数

(三)ArrayIndexOutOfBoundsException  数组小于或大于实际的数组大小

(四)NullPointerException  尝试访问null对象成员

(五)ClassNotFoundException   不能加载所需的类(常见于多态中向下转型)

(六)InputMismatchException   欲得到的数据类型与实际输入的类型不匹配

(七)IllegalArgumentException 方法接收到非法参数

(八)ClassCastException  类强转异常。假设有类A和B(A不是B的父类或子类),O是A的实例,那么当强制将O构造为类B的实例时抛出该异常。该异常经常被称为强制类型转换异常。

        这些常见的异常都是Runtime异常,发送这些异常时,我们都要知道是怎么修改。当然还有其他的异常需要记住的,比如IO异常,上面只是一些比较基础的。

 

四、Throwable类的几种常用方法

  1. toString() 输出该异常的类名。
  2. getMessage() 输出异常的信息,需要通过构造方法传入异常信息(例如病态信息)。
  3. printStackTrace() 打印栈信息。

五、异常的两种处理方式

方式一:捕获处理

1.捕获处理的格式

try{
    可能发生异常的代码
}catch(捕获的异常类型  变量名){
    处理异常的代码
}   
public class Main {
    public static void main(String[] args)
    {
        int[] arr = null;
        div(4,0,arr);
    }

    public static void div(int a , int b,int[] arr){
        int c = 0;
        try{
            c = a/b;  //jvm在这句话的时候发现了不正常的情况,那么就会创建一个对应的异常对象,跳转至catch部分
            System.out.println("数组的长度:"+ arr.length);//该异常不会被捕获到
        }catch(ArithmeticException e){
            System.out.println("出现了算术异常!");
            System.out.println("toString:"+ e.toString());
        }catch(NullPointerException e){
            System.out.println("出现了空指针异常!");
            System.out.println("toString:"+ e.toString());
        }catch(Exception e){
            System.out.println("出现了未知异常!");
        }
        System.out.println("c="+c);
    }
}

2.捕获处理要注意的细节:

  1. 如果一个try块中出现了异常的代码,经过处理之后,那么try-catch块外面的代码可以正常执行。
  2. 如果一个try块中出现了异常的代码,那么在try块中出现异常的代码后面 的语句无法执行。
  3. 一个try块后面可以跟多个catch块,也就是一个try块可以捕获多种异常的类型,但是捕获的异常类型必须从小到大进行捕获。
//如将上例打代码改写为如下,将无法通过编译
try{
    c = a/b;  
    System.out.println("数组的长度:"+ arr.length);
}catch(Exception e){
    System.out.println("出现了未知异常!");
}catch(ArithmeticException e){//Exception 'java.lang.ArithmeticException' has already been caught
    System.out.println("出现了算术异常!");
    System.out.println("toString:"+ e.toString());
}catch(NullPointerException e){//Exception 'java.lang.NullPointerException' has already been caught
    System.out.println("出现了空指针异常!");
    System.out.println("toString:"+ e.toString());
}

 

方式二:抛出处理(throw throws)

1.抛出处理的格式

try{
    fun()//可能发生异常的代码
}catch(捕获的异常类型  变量名){
    处理异常的代码
}
......
fun()throws 抛出的异常类型{
    if(异常发生){
        throw new 异常类型();
    }
}
public class Main {
    public static void main(String[] args)
    {
        try{
            int[] arr = null;
            div(4,0,arr);     //调用了一个 声明抛出异常类型 的方法
        }catch(Exception e){    //这里使用了多态
            System.out.println("出现异常了...");
            e.printStackTrace();
        }

    }

    public static void div(int a, int b,int[] arr) throws Exception {  //声明异常
        if(b==0){
            throw new ArithmeticException(); //抛出一个异常对象...
        }else if(arr==null){
            throw new NullPointerException();
        }
        int c = a/b;
        System.out.println("c="+c);
    }
}

2.抛出处理要注意的细节:

  1. 如果一个方法内部抛出了一个编译时异常对象,那么该方法必须要声明抛出。
  2. 如果调用了一个声明抛出编译时异常的方法,那么调用者必须要处理。
  3. 如果一个方法抛出了一个异常对象,那么该方法也会马上停止(一个方法遇到了throw关键字,那么该方法就会马上停止)
  4. 在一种情况下只能抛出一种异常对象。

注意:throw 关键字是用于方法体之内抛出异常对象的,throws是用于方法声明上,声明抛出异常类型的

六、自定义异常

在实际程序设计中,可能会遇到Java提供的标准异常类没有能够充分的描述清楚当前设计中的问题,这时就需要按照Java封装问题对象的思想,对特有的异常进行自定义异常的封装;

(1).如何自定义异常类:

定义一个派生于Exception的类,或者派生于Exception子类的类;

如果希望该自定义异常具备RuntimeException的一些特性,可以继承RuntimeException类;

这样可以让该自定义异常具备可抛性,同时具备操作异常的一些共性方法;

(2).自定义异常类的初始化:

Throwable和Exception类中都定义了无参的默认构造方法以及带有描述信息的有参构造方法;

//自定义异常类;
class XxxException extends Exception	//也可以根据需要继承RuntimeException;
{
	//默认的构造方法;
	XxxException(){}
	//有参构造方法;
	XxxException(String message)
	{
		super(message);		//直接调用父类的构造方法;
	}
}

 七、异常在子父类覆盖中的体现

       (1).子类方法覆盖父类方法时,如果父类方法抛出了异常,那么子类的覆盖方法只能抛出父类方法所抛异常或是其子类异常,或者不抛异常;

        (2).子类方法覆盖父类方法时,如果父类方法抛出多个异常,那么子类的覆盖方法只能抛出父类方法所抛异常的子集;

       (3).如果父类或者接口中的方法没有抛出异常,那么子类在覆盖方法时,也不能抛出异常;但是如果子类方法确实可能发生异  常,就必须进行try/catch处理,不能在方法上声明异常;

八、异常的转换

    

在catch子句中可以抛出一个异常,这样做的目的是改变异常的类型;

(1).如果捕获到的异常处理不了,但是并不属于该功能出现的异常,可以将异常转换后,再抛出和该功能相关的异常;

(2).捕获的异常能够处理,当需要将异常产生的和本功能相关的问题提供出去让调用者知道并处理,也可以将捕获的异常处理后,在转换为新的异常抛出;

try

{

throw new AException();//try代码块中可能出现的异常;

}

catch(AException e)   //catch进行捕获;

{

.......           //可以对之前捕获的异常作一定的处理;

throw new BException();//抛出另外异常;

}

异常的好处

(1).提高了安全性;

(2).按照面向对象的思想对问题进行封装,处理起来更加方便;

(3).将正常流程代码和异常处理代码以及必要的管理资源代码相分离,方便于阅读;

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值