• 异常和异常处理


    1、异常体系结构

    1.1 什么是异常?

      Java将程序执行过程中发生的不正常情况成为异常。Java使用统一的异常机制来提供一致的错误报告模型,从而使程序更加健壮。

      编程的错误分为语法错误、逻辑错误、异常三种,其中语法错误和逻辑错误不属于异常。因为如果发生语法错误,Java程序根本无法运行;而如果发生逻辑错误,Java程序也不可能得到正确的结果。我们说的异常是指程序既没有语法错误,也没有逻辑错误,而是在运行过程中遇到一些程序以外的错误,导致Java程序发生异常,从而导致Java程序崩溃

    1.2 异常的分类

      Java将程序执行时可能发生的错误(Error)或异常(Exception),都封装成了类,作为java.long.Throwable的子类,即Throwable是所有错误或异常的超类。

    • 错误:指的是Java虚拟机无法解决的严重问题,一般不编写针对性的代码进行处理。
    • 异常:指其他因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。

      异常的种类有很多,如空指针异常、类型转换异常、数组下标越界异常等,java将这些异常归为运行时异常(RuntimeException)。针对运行时异常,java编译器将不会给出任何提醒,因此运行时异常又称为非受检异常.

    1.3 常见的异常和错误类型

    • ArrayIndexOutOfBoundsException:数组小标越界异常。
    • NullPointerException:空指针异常。
    • ClassCastException:类型转换异常。
    • ArithmeticException:算术异常.
    • InputMismatchException:输入不匹配异常。
    • NumberFormatException:数字格式化异常。
    • StackOverflowError:栈内存溢出错误。
    • OutOfMemoryError:内存溢出错误。

    2、异常处理

      通常情况下,异常处理方式有以下三种:

    • 在当前方法发生异常的代码处直接捕获并处理。这种方式对调用者来说,可能完全不知道被调用方法发生了异常。
    • 在当前方法中不处理,直接抛给调用方处理。这种方式会导致当前方法运行中断,退回到调用防的调用代码处进行处理。
    • 当某些代码不满足语法要求或业务逻辑时,可以手动创建符合语法要求的异常对象,然后抛出。除此之外,在当前方法中捕获了某个异常对象时,也可以将异常对象包装为新类型后再抛给调用方处理。

    2.1 try-catch-finally

    package Exception;
    
    import java.util.InputMismatchException;
    import java.util.Scanner;
    
    public class TestTryCatch {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
    
            while(true){
                try{
                    System.out.println("请输入整数被除数:");
                    int a = input.nextInt();
    
                    System.out.println("请输入整数除数:");
                    int b = input.nextInt();
    
                    int result=a/b;
                    System.out.println("商是:"+result);
                    break;
                }catch (ArithmeticException e){
                    e.printStackTrace();
                    System.out.println("除数不能为0");
                }catch (InputMismatchException e){
                    e.printStackTrace();
                    System.out.println("被除数和除数都必须是整数!");
                    input.nextLine();//读取流中的非整数数据,否则死循环
                }finally {
                    System.out.println("计算结束");
                }
                System.out.println("请重新输入!");
            }
            System.out.println("程序结束");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

      情况一:没有异常发生

    image-20220919171246878

      情况二:发生异常,但是被catch分支捕获

    image-20220919171322034

    image-20220919171336610

    2.2 throws

      有时候在当前方法中,无法确定如何处理该异常,那么可以将throws(异常信息)抛给上一级处理。

      在声明某个方法时,可以通过throws在方法签名中明确需要调用方警惕和处理的异常类型。throws关键字后面可以接一个或多个异常类型。如果有多个异常类型,则使用逗号分割,多个异常类型之间的顺序可以随意。throws后面跟的异常类型,可以是方法中可能产生的异常类型本身或其父类异常类型。

    package Exception;
    
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.util.Scanner;
    
    public class TestThrows {
        public static void readFile(String filePathName) throws FileNotFoundException{
            FileInputStream fis = new FileInputStream(filePathName);
            //此处省略具体读文件代码
        }
    
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            while(true){
                try {
                    System.out.println("请指定要读取的文件:");
                    String filePathName=input.next();
                    readFile(filePathName);
                    break;
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                    System.out.println("文件不存在");
                    System.out.println("请重新指定");
                }
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    2.3 throw

      创建异常对象使用关键字new,抛出异常对象使用关键字throw

    2.4 throw和throws的区别

    • throws:可看作try-catch-finally之外的另一种处理异常的方式。在方法声明处,指明可能抛出的一个或多个异常类型,并由方法的调用方进行进一步处理。
    • throw:可看作自动生成并抛出异常对象之外的另一种生成异常对象的方式,属于手动抛出。在方法体内使用,后面跟异常对象。如果程序执行时运行了throw结构,则需要进一步考虑使用try-catch或throws进行处理。

    3、自定义异常

      异常类型虽然也是一个Java类,但不是所有的Java类都可以作为异常类型。Java规定异常或错误的类型必须继承现有的Throwable或其子类。因为只有当对象是Throwable(或其子类之一)的实例时,才能通过Java虚拟机或throw语句抛出。类似地,只有此类或其子类之一才可以是catch子句中的参数类型。

      通常我们会继承ExceptionRuntimeException,而继承RuntimeException的异常是非受检异常,继承Exception的异常是受检异常。此外,为了方便地创建异常对象,我们还可以提供多个构造器

      年龄非法异常代码:

    import java.util.Scanner;
    
    public class ExceptionTest {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
    
            while(true){
                try{
                    System.out.println("请输入年龄:");
                    int age=input.nextInt();
                    if(age>120||age<0){
                        throw new AgeIllegalException("年龄必须在[0,120]之间!");
                    }
                    System.out.println("年龄:"+age);
    //                break;
                }catch (AgeIllegalException e){
                    System.out.println("请重新输入,原因是:"+e.getMessage());
                }
            }
        }
    }
    class AgeIllegalException extends Exception{
        public AgeIllegalException() {
            super();
        }
    
        public AgeIllegalException(String message) {
            super(message);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    image-20220919173110456

      登录异常:

    import java.util.Scanner;
    
    public class LoginTest {
        public static void login(String username, String password) {
            if (!("codeleader".equals(username))) {
                throw new LoginException("用户名不存在!");
            }
            if (!("123".equals(password))) {
                throw new LoginException("密码不正确!");
            }
        }
    
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            System.out.println("请输入用户名:");
            String username = input.next();
    
            System.out.println("请输入密码:");
            String password = input.next();
            try {
                login(username,password);
                System.out.println("登录成功");
            } catch (Exception e) {
                System.out.println("登录失败,原因是:"+e.getMessage());
            }
        }
    }
    
    class LoginException extends RuntimeException {
        public LoginException() {
            super();
        }
    
        public LoginException(String message) {
            super(message);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    image-20220919173201448

    image-20220919173228360

  • 相关阅读:
    python异步编程之asyncio高阶API
    网页期末作业 基于HTML+CSS中国传统节日【清明节】带论文8000字
    小米影像战略升级,开启移动影像新未来
    CTFHUB SSRF
    什么是大票零担?ZETA如何实现大票零担货物追踪可视化?
    【LeetCode】687. 最长同值路径
    开源的网易云音乐API项目都是怎么实现的?
    torch.hub.load()函数的使用——联网加载权重以及如何加载本地权重
    day51_mybatis
    拒绝for循环,从take_along_axis开始
  • 原文地址:https://blog.csdn.net/qq_43753724/article/details/126938381