java 异常进阶 多异常和自定义异常详解

目录

一、前言:

二、多异常的处理:

        Δ前言:

        1.处理方式一:

                代码演示:

        2.处理方式二:

                代码演示:

        3.处理方式三:

                代码演示:

三、PS:finally代码块中存在return的问题:

        代码演示:

四、子父类异常:

        1.子父类异常的关系:

        2.代码演示①:

        3.代码演示②:

五、自定义异常:

        1.介绍:

        2.格式:

        3.注意事项:

        4.代码演示:

                ①自定义异常类:

                ②测试自定义异常:

六、完结撒❀:


一、前言:

        大家好,这篇博客是对java异常基础篇的一个内容延申和补充,主要和大家分享一下多异常的三种处理方式自定义异常介绍自定义异常的定义和使用等等,感谢阅读。              

二、多异常的处理:

        Δ前言:

        多异常,即代码中出现了多个异常

        多异常的处理方式:

         1.分别捕获,并分别处理

         2.一次捕获,但多次处理

         3.一次捕获,且一次处理

        1.处理方式一:

        1.分别捕获,并分别处理

        我们首先来看一下以下代码段:

int[] array = {1, 2, 11, 985, 5};
System.out.println("我想访问数组索引为5的元素:" + array[5]);

        显然,直接运行上述代码,会报异常ArrayIndexOutOfBoundsException(数组下标越界异常)。我们再来看看另一代码段:

int i = 10 / 0;
System.out.println("The value of i is : " + i);

        显然,直接运行这段代码会报异常ArithmeticException(运算中的异常)。

        so,up就以这两个异常为栗,给大家演示以下多异常的处理。     

                代码演示:

package knowledge.exception.advance;

public class MultipleAnomaly {
    public static void main(String[] args) {
        /*
            利用try...catch捕获
         */
    //1.分别捕获,并分别处理
        try {
            int[] array = {1, 2, 11, 985, 5};
            System.out.println("我想访问数组索引为5的元素:" + array[5]);
        } catch (ArrayIndexOutOfBoundsException arrayIndexE) {
            System.out.println(arrayIndexE);
        }

        try {
            int i = 10 / 0;
            System.out.println("The value of i is :" + i);
        } catch (ArithmeticException ariE) {
            System.out.println(ariE);
        }
    }
}

                运行结果:


        2.处理方式二:

        2.一次捕获,但多次处理

        实现方式一个try,多个catch

        Δ注意事项 :

        catch语句里面定义的异常变量,如果存在子父类关系,那么子类的异常变量必须定义在父类异常变量的上面,否则就会报错。 eg : 下面代码段:

try {
    int i = 10 / 0; 
    int[] array = {1, 2, 11, 985, 5};
    System.out.println("我想访问数组索引为5的元素:" + array[5]);
} catch (Exception e) {
    System.out.println(e);
} catch (ArrayIndexOutOfBoundsException arrayIndexE) {
    System.out.println(arrayIndexE);
}

        报错情况如下图所示

        正如IDEA所说的,该异常已经被捕获了。         

        报错原因:

        try中如果出现了异常对象,会把异常对象抛出给catch处理,抛出的异常对象, 会从上至下依次赋值给catch中定义的变量。 如果是子类变量在前,父类变量在后(即正常情况下),因为父类异常对象本身就无法赋值给子类异常对象, 因此try会自动跳开,最终子类异常对象赋值给子类异常变量,父类异常对象赋值给父类异常变量;

         但是,

         如果是父类变量在前,子类变量在后,因为子类异常对象本身是可以赋值给父类异常对象的, 就是多态嘛。因此try不会跳开,而是将子类异常对象也赋值给了父类异常变量,这就导致 下面定义子类异常变量的catch语句是多余的语句,因此报错。

                代码演示:

package knowledge.exception.advance;

public class MultipleAnomaly {
    public static void main(String[] args) {

    //2.一次捕获,但多次处理
        try {
            int i = 10 / 0; //直接运行这段代码会报异常ArithmeticException
            int[] array = {1, 2, 11, 985, 5};
            System.out.println("我想访问数组索引为5的元素:" + array[5]);
        } catch (ArithmeticException ariE) {
            System.out.println(ariE);
        } catch (ArrayIndexOutOfBoundsException arrayIndexE) {
            System.out.println(arrayIndexE);
        }
        System.out.println("---------------------------------");
        /*
            try中若出现异常,会立刻跳转至catch,此处当执行到int i = 10 / 0; 时,就会跳转至
            catch语句,因此控制台只会打印出ArithmeticException
         */
    }
}

                运行结果

                


        3.处理方式三:

        3.一次捕获,且一次处理

        刚刚我们讲到了为什么多个catch语句中子类异常变量必须定义在父类异常变量的前面。其实,一次捕获一次处理,也是应用了这个原理。怎么做到一次处理?直接给它定义一个父类异常的异常变量不就完了么。

        直接定义一个父类异常变量,那么try无论是父类本身的异常对象抛给catch,还是它的子类对象抛给catch ,父类异常变量都可以做接收,一劳永逸!       

                代码演示:

package knowledge.exception.advance;

public class MultipleAnomaly {
    public static void main(String[] args) {
    //3.一次捕获,且一次处理
        try {
            int[] array = {1, 2, 11, 985, 5};
            System.out.println("我想访问数组索引为5的元素:" + array[5]);
            int i = 10 / 0; 
        } catch (Exception e) {
            System.out.println(e);
        }
        /*
            直接定义异常类父类Exception,可以接收绝大多数的异常对象。
         */
    }
}

                运行结果:        

                注意,这里我们先产生了数组下标越界异常(ArrayIndexOutOfBoundsException),立刻便跳转到catch语句,因此控制台只打印出了ArrayIndexOutOfBoundsException。

三、PS:finally代码块中存在return的问题:

        如果finally中含有return语句,会永远只返回finally中return的结果 因此要避免此情况发生。

        PS : 注意!

        ①若finally代码块之前的catch语句中也有return语句,那么该return语句中的内容也会执行!(eg : return ++i; )。只不过执行后并不会由当前return语句返回,而是在底层用一个临时变量temp保存了该返回值,最终的返回值仍是以finally代码块中的return语句为准。若finally代码块中无return语句,才会返回去执行之前的return语句,最终返回temp变量保存的值。

        ②有时会出现try-finally的搭配,这种用法相当于没有捕获异常,因此若出现异常程序会直接崩掉。适用于“执行一段代码,不管有没有出现异常都要执行某个业务逻辑”的场景。

        代码演示:

package knowledge.exception.advance;
/*
    如果finally中含有return语句,会永远返回finally中的结果
    因此要避免此情况发生。
 */
public class FinallyReturn {
    public static void main(String[] args) {
        int number = getNumber();
        System.out.println("The value of number is : " + number);
    }

    public static int getNumber() {
        int i = 11;
        try {
            return i;
        } catch (Exception e) {
            System.out.println(e);
        } finally {
            i = 5;
            return i;
        }
    }
}
//最终的返回值是5

                运行结果

四、子父类异常:

        1.子父类异常的关系:

                关于子父类的异常:

                 ①如果父类中抛出多个异常,子类重写父类方法时, 抛出和父类相同的异常,或者是父类异常的子类,或者不抛出

                ②如果父类中没有抛出异常,子类重写父类该方法时, 也不可抛出异常。此时子类若产生了异常,只能做捕获处理,不能声明抛出

                人话:

                 只要子类和父类保持一致,就不会出事儿。

        2.代码演示①:

        由于代码中的方法涉及到了读取文本文件,up先给大家看一下文本文件1.txt中内容,如下:

        

        我们以Father1类作为第一个演示类,Father1类代码如下:

package knowledge.exception.advance;

import java.io.*;

public class Father {
    public void readText() throws IOException {
        Reader reader = new FileReader("D:\\JAVA\\IDEA\\file\\1.txt");
        int data;

        while ((data = reader.read()) != -1) {
            System.out.println((char)data);
        }

        reader.close();
    }

    public void readFile() throws IOException {
        throw new IOException("😋抛出一个IO父类异常对象");
    }

    public void getElement() throws IndexOutOfBoundsException {
        System.out.println("这是父类的方法");
    }
}

class Son extends Father{
//1.父类抛出异常时
    @Override
    //1_①抛出和父类相同的异常
    public void readText() throws IOException {
        Reader reader = new FileReader("D:\\JAVA\\IDEA\\file\\1.txt");
        char[] charArray = new char[1024];  //用于读写数据的字符数组的长度最好是1024的整数倍
        int data;

        while ((data = reader.read(charArray)) != -1) {
            System.out.println(charArray);
        }

        reader.close();
    }
    //1_②抛出父类异常的子类
    @Override
    public void readFile() throws FileNotFoundException {
        throw new FileNotFoundException();
    }

    //1_③不抛出异常
    @Override
    public void getElement() {
        System.out.println("这是子类的方法");
    }
}

class Test1 {
    public static void main(String[] args) throws IOException {
        Father f = new Father();
        Son s = new Son();

        f.readText();
        System.out.println("-----------------------------------");
        s.readText();

        f.readFile();
        f.getElement();

        s.readFile();
        s.getElement();
    }
}

                运行效果(GIF图):

  

        3.代码演示②:

        up以Father2类作为第二个演示类,来演示如果父类没有抛出异常的情况下,子类的处理情况。Father2代码如下:

package knowledge.exception.advance;

public class Father2 {
    public void f() {
        System.out.println("父类没有抛出任何异常。");
    }
}

class Son2 extends Father2 {
//2.父类没有抛出异常时
    @Override
//    public void f() throws Exception{                 //如果此时子类声明异常,编辑器会报错。
//        System.out.println("此时子类也不能抛出任何异常");
//    }
    public void f() {
        System.out.println("此时子类也不能抛出任何异常");
        System.out.println("假设子类重写方法时产生了异常,也只能捕获处理,不可以抛出异常对象!");

        try {
            throw new Exception("无聊抛出一个异常对象玩玩儿😁");
        } catch (Exception e) {
            e.printStackTrace();    //这个方法在异常基础篇分享过
        }
    }
}

class Test2 {
    public static void main(String[] args) {
        Father2 ff = new Father2();
        Son2 ss = new Son2();

        ff.f();
        System.out.println("--------------------------------------");
        ss.f();
    }

}

                运行效果

五、自定义异常:

        1.介绍:

        java中本身已经定义了许多的异常类,但是某些情况下仍然不够我们霍霍的,所以需要我们自己去定义一些异常类。

        2.格式:

        public class ___Exception extends Exception / RuntimeException {

                //自定义的异常类内部,需要定义两个构造方法

                //一个空参构造

                //一个带参构造(说明异常信息)

        }

        3.注意事项:

        ①自定义异常类的类名一般都是以"Exception"作为结尾,以达到见名知意的效果,表示该类是一个异常类

        ②自定义的异常类,必须得继承Exception类或者RuntimeException类

        继承Exception类,表示自定义的异常类是一个编译期异常

        继承RuntimeException类,表示自定义的异常类是一个运行期异常;      

        关于编译期异常和运行期异常区别以及处理方式,我们在java异常基础篇已经讲过,此处不再赘述。

        4.代码演示:

                ①自定义异常类:

                我们创建一个RegisterException类的自定义异常类,当我们模拟注册用户时,如果用户输入的用户名异常,则可以抛出RegisterException类的异常对象。

                RegisterException类代码如下:

package knowledge.exception.advance;

public class RegisterException extends Exception {
    //1.添加一个空参构造
    public RegisterException() {
        super();    //默认调用父类的空参构造
    }

    //2.添加一个带参构造(说明异常信息)
        /*
            查看源码发现(IDEA快捷键Ctrl + b可查看类的源码),所有的异常类都会有
            一个带异常信息的构造方法,让父类来处理这个异常信息。
         */
    public RegisterException(String message) {
        super(message);
    }
}

                ②测试自定义异常:

                有了自定义的异常类,接着我们就可以创建一个测试类来测试自定义异常类,这里我们以TestRegisterException类作为演示类,需求 :模拟注册用户的操作,如果用户名已经存在,则抛出RegisterException异常并提示用户: 这个用户名已经注册过了哈

                TestRegisterException类代码如下:                

package knowledge.exception.advance;

import java.util.Scanner;

/*
    requirement : 模拟注册用户的操作,如果用户名已经存在,则抛出RegisterException异常并提示用户:
                  这个用户名已经注册过了哈。

    mentality(思路) :
            1.首先,可以使用一个数组来保存已注册的用户名,模拟数据库。
            2.其次,可以使用Scanner类获取用户想注册的用户名,模拟前端页面。
            3.定义一个方法,对用户输入的用户名进行判断。
                若已存在该用户名,抛出RegisterException异常并提示用户:这个用户名已经注册过了哈。
                若不存在该用户名,提示用户:注册成功🌶!
 */
public class TestRegisterException {
    public static void main(String[] args) throws RegisterException {
    //1.首先,可以使用一个数组来保存已注册的用户名,模拟数据库。
        String[] names = {"大伟哥", "赵鑫鑫", "杜兰特", "Cyan", "王五"};

    //2.其次,可以使用Scanner类获取用户想注册的用户名,模拟前端页面。
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入你想注册的用户名:");
        String userName = sc.nextLine();

        ifExist(names, userName);

        sc.close();
    }

    //3.定义一个方法,对用户输入的用户名进行判断。
    public static void ifExist(String[] names, String userName) throws RegisterException {
        int temp = 0;
        for (String name : names) {
            if (name.equals(userName)) {
                temp = -1;
                throw new RegisterException("这个用户名已经注册过了哈。");
            }
        }
        if (temp == 0) {
            System.out.println("注册成功🌶!");
        }
        /*
            加入这个判断条件更严谨,以不会导致在抛出异常对象后仍然打印出"注册成功🌶!"的提示信息。
            其实还有多种处理方式,比如在抛出异常对象后执行return语句,直接结束方法体,都可以。
         */
    }
}

                运行效果如下GIF图:

六、完结撒❀:

        恭喜你看到这里,感谢阅读。

System.out.println("------------------------------------------------------------------------------------"); 

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
完整全套资源下载地址:https://download.csdn.net/download/qq_27595745/70761177 【完整课程列表】 完整版Java web开发教程PPT课件 Java开发教程 第01章 JavaScript简介以及基本语法(共15页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第02章 Dom模型,控制客户端元素(共15页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第03章 表单验证,常用函数(共15页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第04章 自定义web服务器(共14页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第06章 SERVLET(共15页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第07章 JSP语法及运行过程(共13页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第08章 JSP内置对象(共22页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第09章 jstl、el、java bean(共18页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第10章 过滤器、监听器、自定义标签(共19页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第11章 AJAX实现(共11页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第12章 自定义mvc框架(共11页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第13章 spring ioc aop(共18页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第14章 spring mvc介绍,原理以及搭建(共15页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第15章 spring mvc核心对象拦截器(共26页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第17章 自定义orm框架(共11页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第18章 mybatis框架的搭建以及应用(共13页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第19章 mybatis高级应用(共21页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第20章 数据库连接池,缓存(共15页).pptx 完整版Java web开发教程PPT课件 Java开发教程 第22章 常用框架的介绍以及环境搭建(共16页).pptx JS课程案例ebookHTML\网上书店需求文档.doc

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cyan_RA9

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值