异常

异常

​ 异常是指在程序的运行过程中所发生的的不正常事件,它会中断正在运行的程序.

​ 程序运行 ---->异常 ---->程序中断运行

​ 在写程序代码的时候,总会难免出现一些异常(Bug).如果每发现一个异常就去加条件限制来修复异常,代码就会显得臃肿,并且需要耗费大量精力去堵漏洞.这时候就需要在程序中加入异常处理机制.

​ 异常处理机制:

​ 程序中预先设置好对付异常的处理方法 ---->程序运行 —>异常 —>对异常进行处理 —>处理完毕,程序继续运行(不会中断程序运行)

​ Java中的异常处理是通过5个关键字来实现的,分别是:try、catch、finally、throw、throws


在这里插入图片描述

try-catch结构

​ 使用try-catch块捕获异常,会有三种情况出现:

1、程序正常运行

	public void method(){
        try{
            //代码段(此处不会产生异常)
        }catch(异常类型 ex){
            //对异常进行处理的代码段
        }
        //代码段
    }

​ 在这种情况下,程序执行完try块中的代码段后,将不会进入catch里的代码,而直接执行catch代码块后面的代码段.

在这里插入图片描述

2、出现异常,并且异常类型匹配

 	public void method(){
        try{
            //代码段1
            //产生异常的代码段2
            //代码段3
        }catch(异常类型 ex){
            //对异常进行处理的代码段4
        }
        //代码段5
    }

​ 在这种情况下,代码在try块进行到异常的代码段2后,就不再执行代码段3,而是跳到catch中去与捕捉异常类型进行匹配,匹配成功后,就会执行catch中的代码段4,然后再进行catch后的代码段5.

在这里插入图片描述

3、出现异常,但异常类型不匹配
	 	public void method(){
        try{
            //代码段1
            //产生异常的代码段2
            //代码段3
        }catch(异常类型 ex){
            //对异常进行处理的代码段4
        }
        //代码段5
    }

​ 这种情况下,程序在运行到try块中的代码段2后,不再运行代码段3,而是跳到catch中去进行异常类型匹配判断,发现类型匹配不上,程序直接终止,不再执行后面的代码.

在这里插入图片描述

在catch块中处理异常,有以下几个方法可以用到:

System.err.println(String msg);

​ 加入用户自定义处理信息,并在控制台以红色字体打印输出信息

(void) printStackTrace();

​ 调用方法输出异常信息,输出异常的堆栈信息.

在这里插入图片描述

(String) getMessage();

​ 返回异常信息描述字符串,是printStackTrace()输出信息的一部分内容

常见的异常类型

异常类型说明
Exception异常层次结构的父类
ArithmeticException算术错误情形,如以零作为除数
ArrayIndexOutOfBountsException数组下标越界
NullPointerException尝试访问null对象成员
ClassNotFoundException不能加载所需的类
IllegalArgumentException方法接受到非法参数
ClassCastException对象强制类型转换出错
NumberFormatException数字格式转换异常,如把"abc"转换成数字

try-catch-finally结构

	try{
        //代码块1
    }catch(异常类型 ex){
        //处理异常的代码块2
    }finally{
        //代码块3
    }

​ 在try-catch块后面加入finally块,无论程序运行是否有异常,finally块里的代码段都会执行

​ 无异常时,try —>finally

​ 有异常时,try —> catch —> finally

​ finally代码块唯一不执行的一种情况是,在try或catch中出现System.exit(i);语句。

​ 当运行到System.exit(1)语句时,程序中断,退出Java虚拟机,finally中的代码将不执行。

​ 需要注意的是,try-catch-finally结构中,try语句块是必须的,但catch和finally语句块可选择写或不写,但二者必须至少出现一个,即try-catch、try-finally、try-catch-finally三种。

存在 return的try-catch-finally结构
	public void method(){
        try{
            //代码段1
             return;
        }catch(异常类型 ex){
            //对异常进行处理的代码段3
        }finally{
            //代码段4
        }
    }
	public void method(){
        try{
            //代码段1
            //产生异常的代码段2
        }catch(异常类型 ex){
            //对异常进行处理的代码段3
            return;
        }finally{
            //代码段4
        }
    }

​ 在以上两段代码中,分别为在try块中加入了return和在catch块中加入了return,无论是哪种情况,程序运行都将先运行finally块中的代码,最后才执行return跳出方法。

在这里插入图片描述

多重catch块

​ 在一段代码中,运行时可能会引发不止一种异常,这时候异常处理的catch捕获可以使用多重catch来捕获多种类型的异常,但有几点需要注意:

1、排列catch语句的顺序:先子类后父类

2、发生异常时按顺序逐个匹配

3、只执行第一个与异常类型匹配的catch语句

	try{
        //异常代码段1
    }catch(异常类型1 a){
        //处理异常1的代码段
    }catch(异常类型2 b){
        //处理异常2的代码段
    }catch(异常类型3 c){
        //处理异常3的代码段
    }
	...
	}finally{
        //代码段4
    }

声明异常

​ 如果在一个方法体中抛出了异常,为了通知调用者,需要用throws来声明某个方法可能抛出的各种异常,多个异常用逗号隔开。

	public void divide() throws ArithmeticException,InputmismatchException{
        .....
    }

​ 调用者在调用存在异常的方法时,需要自己处理方法中的异常,或者继续声明异常,让更外一层的方法来处理异常。如果在main()方法中声明的异常,就由Java虚拟机进行处理。

(1)继续声明异常
	public static void main(String[]args) throws ArithmeticException,InputmismatchException{
        Test t =new Test();
        t.divide();
    }
(2)调用者处理异常
	public static void main(String[]args){
        Test t =new Test();
        try{
            t.divide();
        }catch(ArithmeticException a){
            //代码块1
        }catch(InputmismatchException i){
            //代码块2
        }finally{
            //代码块3
        }
    }

抛出异常

​ 除了系统自动抛出异常外,有些问题还需要程序员自行抛出异常。我们通过在方法体中使用throw来抛出异常,后面必须try-catch处理异常或用throws声明抛出的异常。

	public void setSex(String sex) throws Exception{
        if(sex.equals("男") || sex.equals("女")){
            this.sex = sex;
        }else{
            throw new Exception("性别只能为男女!")
        }
    }

throw 和throws的区别

​ 我们可以看到,抛出异常的时候使用到了throw和throws,两个单词长得差不多,但却是不一样的,throw是用来手动抛出异常的,throws是用来声明抛出的异常的。

throwthrows
生成并抛出异常声明方法内抛出了异常
位于方法体内部,可作为单独语句使用必须跟在方法参数列表后面,不能单独使用
抛出一个异常对象,且只能是一个声明抛出异常类型,可以跟多个异常,通过逗号隔开

异常体系结构

在这里插入图片描述

图中可以看到,Object为所有类的父类,Throwable为异常中最高层的父类,它的子类有Error和Exception两种。

Error类异常是仅靠程序本身无法恢复的严重错误,通常是需要去终止程序的。比如内存不足,jvm溢出等。

Exception类异常是由Java应用程序抛出和处理的非严重错误,这类异常是可以处理修复的,通常是希望处理掉异常而不去终止程序。

而Exception类中又可以划分为两类异常:

1、Checked异常。检查时异常,在编译的时候不通过,程序必须处理该类异常,不处理就无法运行。

2、运行时异常。是编译的时候系统不去检查,运行时才会报错。在写代码的时候不要求必须进行try-catch处理或者throws声明抛出。RuntimeException是运行时异常类,它下面有很多子类异常平时也很常见,如ArithmeticException类、NullPointerException类、NumberFormatException类等等。

自定义异常

​ 虽然JDK中提供了很多异常类型,但如果JDK中的异常类型不能满足程序的需要时,可以自定义异常类。

使用自定义异常类的步骤:

​ 1、定义异常类

​ 可以继承Throwable类、Exception类、RuntimeException类中的一种,通常不需要编译时检查的就继承RuntimeException类。

​ 2、编写构造方法,继承父类的实现

​ 3、实例化自定义异常对象

​ 4、使用throw抛出

​ 如果是运行时异常类型的异常,throw抛出异常后,不要求必须throws声明抛出的异常也能运行,但会在运行中报错。

public class PersonException extends Exception{

	public PersonException() {
		super();
	}

	public PersonException(String message) {
		super(message);
	}	
}

public class Person {
	private int age;

	public int getAge() {
		return age;
	}

	public void setAge(int age) throws PersonException{
		if(age<0 || age>100) {
			throw new PersonException("年龄必须在1到100之间!");
		}
		this.age = age;
	}
}
异常链

​ A方法调用B方法时,B方法却抛出了异常。那么A方法继续抛出原有的异常还是抛出一个新的异常呢?

​ (1)抛出原有的异常

​ A方法与B方法进行了关联,不便于代码修改和扩展

​ (2)抛出新的异常

​ 会丢失原有异常信息

​ 而异常链创建了新的异常却保留了原有异常的信息。

异常处理原则

​ 异常处理与性能的原则:

​ 1、异常只能用于非正常情况

​ 2、不要将过于庞大的代码块放在try中(不好定位异常)

​ 3、在catch中指定具体的异常类型(尽量不用Exception父类)

​ 4、需要对捕获的异常做处理(往外throw会影响性能)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值