Java异常处理【第九章】

异常概述

异常可以看作是程序运行时,在运行时可能会出现的一些错误称为异常。

通常使用Exception以及它的子类来封装程序产生的错误。
在这里插入图片描述

异常一般可以分为两类。

  1. RuntimeException:运行时才会出现的异常,一般是代码运行时,逻辑错误而产生的。可以正常编译运行。
  2. 编译时出现的异常,一般是在代码在编译阶段,编译器会自动检测语法规范而产生的。如果没修改异常,那么将无法编译运行。



这段代码就是一个在编译阶段就出现的异常,在编写完这段代码后,编译器就会自动提示错误,编写者必须需要修改报错行的代码,才能运行程序。

Random r=new Random();
int a="123";	// 编译阶段就会被检测出来的异常

在这里插入图片描述




而下面这段代码就是一个只有运行时才可能产生异常的代码,如果随机值是负数或小于10,将会产生一个异常。

int[] arr=new int[r.nextInt()];	// 只有运行后,才能确定是否会产出异常
arr[10]=100;



异常的处理


程序在产生后异常后,如果我们不对该异常进行处理,那么Java虚拟机会采取默认处理方式,程序会在异常产生行处停止,并将异常信息打印在控制台,以便编写者进行代码的修改。


异常出现后,第11行的代码并没有执行,说明异常出现后,程序会在异常行停止运行。
在这里插入图片描述



那该如何对异常进行处理呢?
Java提供了一种机制,异常捕捉进制,简述就是当异常产生后被抛出后,可以使用特定的语句将被抛出的异常进行捕获,并进行处理。



异常的捕捉

Java的异常捕获结构由try、catch和finally3部分组成。


语法使用:

try{
	// 可能产生异常的代码快
}catch(可能产生的异常类型 变量名){
	// 对异常的处理
}
finally{
	// 无论以上代码是否执行,本语句都会执行
}

使用try、catch语句对上述代码进行改写后。

try{
    Random r=new Random();
    int[] arr=new int[r.nextInt()];
    arr[10]=100;
    System.out.println("代码标记位");
}
catch (NullPointerException e){
    System.out.println("空指针引用,出现异常");
}
catch(NegativeArraySizeException e){
    System.out.println("数组大小为负数,出现异常");
}
finally{
    System.out.println("异常处理结束");
}
System.out.println("程序结束");

运行结果

在这里插入图片描述



try语句有下列几个特点。

  1. 如果在try语句内的代码块产生了异常,那么将会被下面的catch语句进行捕获,会和catch语句进行异常类型匹配,如果匹配成功则,进入该catch语句,不在进行后面的catch语句匹配。这点与if else语句类似。
  2. 在异常产生并被捕获后,并在执行完catch语句后,程序不会停止,会继续往下执行。
  3. 如果在try语句内产生异常,但是在catch语句内没有与之匹配的异常类型,那么该异常会交给JVM进行默认处理。
  4. 在try内某行代码产生异常后,在try语句该行以下的程序不会被执行了,将会跳转catch语句进行异常匹配处理。
  5. 如果在try内的代码块,没有出现异常,那么依次将try内的语句执行完毕,不会执行catch语句。



一般的,在try、catch语句中,try语句中不会只产生一种异常,那么对异常类型的匹配catch语句就不会只有一条,那么如果在catch语句内的异常类型有父子关系,那么父类异常的catch语句必须放置在子类异常的catch语句下面。因为父类异常是可以接收子类异常的,可以形成多态的关系,那么拿子类异常进行匹配时,父类异常也是可以接收的。那么如果子类异常放置在父类异常下面,那么子类异常catch将永远不会被执行。


例如在以下代码中,Exception是父类异常,而NullPointerException等是Exception异常的子类,那么两个子类异常匹配将永远不会执行,所以编译器给出了警告。


在这里插入图片描述




finally语句

一个完整的异常处理语句一定要包含finally语句,无论程序中是否有异常产生,并且无论之前的try-catch语句块是否顺序执行完毕,都会执行finally语句。

但是有以下四种特殊情况,finally不会执行。

  1. 在finally语句内出现异常
  2. 在finally语句之前使用了System.exit()退出了程序。
  3. 程序所在的线程死亡
  4. 关闭了CPU

finally只能与try-catch语句配合中,并不能让其单独存在。



Java常见的异常类

Java提供了多种类型的异常类,我们可以选择对应的产生的异常类,使用catch语句进行捕捉,对其进行对应的处理。当然如何看到被JVM默认处理的异常要能大概了解是那种异常,然后对其进行对应的修改。


常见的异常类
在这里插入图片描述



自定义异常类


虽然Java提供了很多的异常类供我们使用,但是如果有一个user的类,类中有一个属性是name,要求这个name需要用户自己输入,并且name的长度需要大于2-小于10,否则抛出一个异常进行处理。那么这个异常该使用那个异常类呢?好像在Java提供的异常类中,没有对应的异常类能够很好的表示出来。

这个时候就需要编写者自己定义一个异常类来使用了。


异常类的定义

public class NameLengthException extends Exception{
	
	public NameLengthException (){
	}
	//创建一个有参构造,使用父类的构造方法
	public NameLengthException(String message){
		super(message);
	}
}

自定义异常要遵守以下两个规范

  1. 异常类的定义与普通类的定义几乎相同,但是,异常类要直接或间接的继承Throwable类,Exception就是Throwable的子类。
  2. 在异常类中一般没有属性与方法,而且其两个构造方法也是调用父类的构造方法。

例如上述的需求,在user中,用户名长度需要遵守大于2小于10的规定,那么我们就可以自定义一个异常类来提醒用户的错误输入。

//定义一个异常类
class NameLengthExcepiton extends Exception{
    public NameLengthExcepiton() {
    }

    public NameLengthExcepiton(String message) {
        super(message);
    }
}
class user{
    private String name;
	
    public user(String name) throws NameLengthExcepiton {
        int len=name.length();
        // 对于出现的错误,将异常抛出
        if(len < 2 || len > 10){
            throw new NameLengthExcepiton(name+"的长度不符合规定");
        }
        this.name = name;
    }
}



自异常一般分为以下几个步骤

  • 创建异常类。
  • 在方法中通过throw关键字抛出异常对象。
  • 如果在当前抛出异常的方法进行处理,那么使用try-catch语句进行处理,否则需要在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,进行下一步操作。
  • 在出现异常的方法的调用者中捕获并处理异常。



End

本文如有错误,欢迎指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值