• java编程基础总结——14.异常处理


    一、异常:

        指的是程序运行过程中,因为用户的误操作、代码的BUG、
        等等一系列原因,引起的程序崩溃的现象,被称为异常

         崩溃:程序无法正常继续执行,在这行代码抛错,抛错操作系统解决不了,也抛了出去最终软       件退出(因为解决不了问题,无法正常运行)

    例:

    1. package com.openlab.day14;
    2. import java.util.Scanner;
    3. public class TestException01 {
    4. public static void main(String[] args) {
    5. Scanner input = new Scanner(System.in);
    6. System.out.print("请输入第一个数:");
    7. int num1 = input.nextInt();
    8. System.out.print("请输入第二个数:");
    9. int num2 = input.nextInt();
    10. int res = divide(num1, num2);
    11. System.out.println(String.format("%s ÷ %s = %s", num1, num2, res));
    12. input.close();
    13. }
    14. private static int divide(int num1, int num2) {
    15. int result = num1 / num2;
    16. return result;
    17. }
    18. }

     

    二、异常处理:

       解决掉异常的现象,让程序继续运行(不要崩溃退出)下去。
        程序容错能力提升!!!!程序就会越稳定!!!

    java进行异常处理,有两种解决方案:
        |-- 抓捕异常【重点掌握】
        |-- 抛出异常

    异常分类:
        1). 编译型异常:
            在源码编译阶段,直接抛出异常,这种异常必须要处理。
            不处理,则无法正常运行代码。

     例:

    异常原因:路径可能不存在

        2). 运行时异常:
            在代码运行时,有可能出现的异常,被称为运行时异常

            一、异常   例就是运行时异常(除零异常)


    1. 抓捕异常:

     针对于可能出现异常的代码,进行抓捕
        
        try {
            // 可能发生异常的代码

        } catch (Exception e) {
            // 如果出现了一次,代码会立刻进入catch中
            // 在这儿解决抓捕到的异常
        } finally {
            // 必须要执行的代码
        }

    try {
        
        } catch(XxxException e) {
            // 异常处理
        } catch(XxxxException e) {
            // 异常处理
        } catch(Exception e) {
            // 异常处理
        } finally {
            // 必须要执行的代码

        }


    如果使用抓捕异常,通过这种处理,程序即便是遇到了,也不崩溃!!!

    1. package com.openlab.day14;
    2. import java.io.File;
    3. import java.util.Scanner;
    4. public class TestException01 {
    5. public static void main(String[] args) {
    6. Scanner input = new Scanner(System.in);
    7. System.out.print("请输入第一个数:");
    8. int num1 = input.nextInt();
    9. System.out.print("请输入第二个数:");
    10. int num2 = input.nextInt();
    11. int res = divide(num1, num2);
    12. System.out.println(String.format("%s ÷ %s = %s", num1, num2, res));
    13. input.close();
    14. }
    15. private static int divide(int num1, int num2) {
    16. int result = 0;//局部变量必须初始化,无默认值。成员变量有默认值
    17. try {
    18. // 如果出现了错误,则立刻进入catch块
    19. result = num1 / num2;
    20. }catch(Exception e){
    21. //只有出现了异常,catch块中的代码才会执行
    22. System.out.println("出现了异常");
    23. }
    24. return result;
    25. }
    26. }


    1)try catch运行流程:

           出现异常的流程:try中出现异常代码之后的代码都不执行,立即跳入catch块,执行完之后再执行后继代码
          不出现异常的流程:只有catch块中的代码不执行。try执行完之后,跳过catch块,直接执行后继代码

    1. package com.openlab.day14;
    2. import java.io.File;
    3. import java.util.Scanner;
    4. public class TestException2 {
    5. public static void main(String[] args) {
    6. Scanner input = new Scanner(System.in);
    7. System.out.print("请输入第一个数:");
    8. int num1 = input.nextInt();
    9. System.out.print("请输入第二个数:");
    10. int num2 = input.nextInt();
    11. int res = divide(num1, num2);
    12. System.out.println(String.format("%s ÷ %s = %s", num1, num2, res));
    13. input.close();
    14. }
    15. private static int divide(int num1, int num2) {
    16. int result = 0;
    17. System.out.println(1);
    18. try {
    19. // 如果出现了错误,则立刻进入catch块
    20. System.out.println(2);
    21. result = num1 / num2;
    22. System.out.println(3);
    23. }catch(Exception e){
    24. System.out.println(4);
    25. //只有出现了异常,catch块中的代码才会执行
    26. System.out.println("出现了异常");
    27. }
    28. System.out.println(5);
    29. return result;
    30. }
    31. }

    不出现异常:

    出现异常:

     

    2)java中异常的继承关系:
        
        Throwable                异常的顶级类
            |-- Error            致命性的错误
            |-- Exception            常见的异常的父类
                |-- RuntimeException    运行时异常,只有运行时,才有可能出现异常
                
                其他的Exception的子类都是编译型异常,必须处理

     

     

    3)多个异常的处理方案:
        最后其他异常可以用Exception e 来抓捕,运用了多态原理。所有异常都是Exception的子类,直接或者间接继承了Exception,根据多态原理,根据父类引用代指所有子类

     try {
        
        } catch(XxxException e) {
            // 异常处理
        } catch(XxxxException e) {
            // 异常处理
        } catch(Exception e) {
            // 异常处理
        }

    1. private static int divide(int num1, int num2, Scanner input) {
    2. int result = 0;
    3. try {
    4. result = num1 / num2;
    5. input.nextInt();
    6. }catch(ArithmeticException e){
    7. e.printStackTrace();
    8. System.out.println("除数不能为零!!!");
    9. }catch(InputMismatchException e){
    10. e.printStackTrace();
    11. System.out.println("请输入整数!!!");
    12. }catch(Exception e){//
    13. e.printStackTrace();
    14. System.out.println("其他异常");
    15. }
    16. return result;
    17. }

    4). finally关键字

             若都在try块中,关键代码在可能触发异常的代码之后,那么一旦触发异常,关键代码将不能被执行。因为异常,程序会直接跳到catch块中。所以java设计finally关键字。

     try {
            // 可能存在异常的代码
        } catch(XxxException e) {
            // 异常处理代码
        } [finally {
        
        
        }] // [ ] 表示可以有,可以没有

    1). 把什么样的代码写在finally中?

        回收垃圾
        关闭IO流
        关闭数据库连接
        ……

        核心必须要执行代码

     2)finally块

            上断代码的关注点不是catch块,只是想执行try后执行finally

            在开发过程中,希望有的代码必须执行,但是不能保证一定执行,可能有异常等跳过代码,所以有这样一种结构。利用finally关键字的作用。

       try {
        
        } finally {
            // 将必须要执行的代码写在finally中!!!
        }


    3). 注意:在开发过程中请注意,return关键字和finally关键字同时出现的情况,认真分析
        仔细考虑

    finally 是在jvm层次执行的,不是在原码层次执行的。代码遇到return,,尤其是函数中,遇到return就会立即返回到调用的位置,在返回前,发现后面有finally,会将返回的状态保存在那里,之后开始执行finally,执行完返回。

    1. package com.openlab.day14;
    2. import java.io.IOException;
    3. public class TestException4 {
    4. public static void main(String[] args) throws IOException {
    5. int res = say();
    6. System.out.println(res);
    7. }
    8. public static int say() {
    9. try {
    10. int a = 10;
    11. return a;
    12. } catch (Exception e) {
    13. } finally {
    14. System.out.println("这儿还会执行吗?");
    15. }
    16. return 0;
    17. }
    18. }

    面试题:下面代码的运行结果?

    1. package com.openlab.day14;
    2. import java.io.IOException;
    3. public class TestException5 {
    4. public static void main(String[] args) throws IOException {
    5. int res = say();
    6. System.out.println(res);
    7. }
    8. public static int say() {
    9. int a = 10;
    10. int b = 20;
    11. try {
    12. b += a++;// b = 30 a = 11
    13. return b;
    14. } catch (Exception e) {
    15. } finally {
    16. a += 10;// a = 21
    17. b += 20;// b = 50
    18. }
    19. return a;
    20. }
    21. }

    finally在return之后执行,但是return的趋势已经形成,一旦return的趋势形成,会将要返回的值临时存储下来,等待后面执行finally之后再将它返回。虽然b = 50,a = 21,但是不影响将30return

    2. 抛出异常:

             将异常交给调用者处理

            编程型异常,如果我们不想处理,可以直接抛给调用者,由调用者完成处理,调用者也不处理,会继续上抛,直到抛给main函数,main函数抛给jvm,jvm尝试处理,发现解决不了,就挂了

     

     

            由此看出,抛出异常并不是永久解决问题的方案,我们抛出异常原因:

            异常不一定会触发,尤其是编译型异常出现,懒得处理(如刚刚的文件例子,有路径异常就出现不了,出现不了就没有问题)

    例:

    1. package com.openlab.day14;
    2. import java.io.File;
    3. import java.io.IOException;
    4. public class TestException4 {
    5. public static void main(String[] args) throws IOException {
    6. String path = "c:/a.txt";
    7. creatFile02(path);
    8. }
    9. private static void creatFile02(String path) throws IOException {
    10. File file = new File(path);
    11. file.createNewFile();
    12. }
    13. private static void creatFile(String path) {
    14. try {
    15. File file = new File(path);
    16. file.createNewFile();
    17. } catch (IOException e) {
    18. e.printStackTrace();
    19. System.out.println("创建失败");
    20. }
    21. }
    22. }

    三、自定义异常类:

            接触到的都是属于java官方提供的异常类,
            有时候自己设计异常类

        自定义异常类:定义一个普通的类,让该类成为成为Exception的子类或Exception类的孙子类

    异常抛出:
        可以通过创建异常(系统或者自定义),来给调用者一个确切的错误信息
        调用者就可以通过抛出的信息做成对应的判断。       

            在自定义异常时,若继承Exception,做的是编译型异常,在编译阶段必须得处理,不建议使用编译型异常。建议使用运行时异常,简化写法

    编译型异常例:

    1. package com.openlab.day14;
    2. public class MyException extends Exception{
    3. private static final long serialVersionUID = -5723348118187732441L;
    4. public MyException() {
    5. super();
    6. }
    7. public MyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
    8. super(message, cause, enableSuppression, writableStackTrace);
    9. }
    10. public MyException(String message, Throwable cause) {
    11. super(message, cause);
    12. }
    13. public MyException(String message) {
    14. super(message);
    15. }
    16. public MyException(Throwable cause) {
    17. super(cause);
    18. }
    19. }
    1. package com.openlab.day14;
    2. public class Test02 {
    3. public static void main(String[] args) {
    4. }
    5. //登录功能
    6. //需要写 throws MyException 。抛出的是编译型异常,往出去抛还得在当前声明,所以不建议使用
    7. public void login(String username, String password) throws MyException {
    8. if(username.equals("admin") && password.equals("123456")) {
    9. System.out.println("登录成功");
    10. }else {
    11. //throws是放在方法上的,用来抛出不处理的异常,处理异常
    12. //throw是人为在底层向调用者抛出异常对象的,制造异常
    13. throw new MyException("对不起,用户名或者密码错误,请重新登录");
    14. }
    15. }
    16. }

    throws和throw区别:

            throws是放在方法上的,用来抛出不处理的异常,处理异常
            throw是人为在底层向调用者抛出异常对象的,制造异常

    运行时异常例:

    1. package com.openlab.day14;
    2. /*
    3. * 在自定义异常时,建议使用运行时异常
    4. */
    5. public class MyException extends RuntimeException{
    6. private static final long serialVersionUID = -5723348118187732441L;
    7. public MyException() {
    8. super();
    9. }
    10. public MyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
    11. super(message, cause, enableSuppression, writableStackTrace);
    12. }
    13. public MyException(String message, Throwable cause) {
    14. super(message, cause);
    15. }
    16. public MyException(String message) {
    17. super(message);
    18. }
    19. public MyException(Throwable cause) {
    20. super(cause);
    21. }
    22. }
    1. package com.openlab.day14;
    2. public class Test02 {
    3. public static void main(String[] args) {
    4. try {
    5. new Test02().login("admin", "admin");
    6. }catch(MyException e) {
    7. //e.printStackTrace();
    8. System.out.println(e.getMessage());
    9. }
    10. }
    11. //登录功能
    12. //编译型需要写 throws MyException 。抛出的是编译型异常,往出去抛还得在当前声明,所以不建议使用
    13. public void login(String username, String password) {
    14. if(username.equals("admin") && password.equals("123456")) {
    15. System.out.println("登录成功");
    16. }else {
    17. //throws是放在方法上的,用来抛出不处理的异常,处理异常
    18. //throw是人为在底层向调用者抛出异常对象的,制造异常
    19. //自定义异常,可以向调用者传递需要的信息
    20. throw new MyException("对不起,用户名或者密码错误,请重新登录");
    21. }
    22. }
    23. }

     

  • 相关阅读:
    沃通CA证书支持多所高校招投标文件电子签名
    外卖点餐小程序源码 扫码点餐小程序源码
    为什么在springboot中使用thymeleaf无法实现网络请求
    Web自动化测试-Selenium语法入门到精通
    GNU gold链接器 - target.cc 实现特定目标架构的支持
    【Codeforces 1367F】 Flying Sort (Hard Version)
    在RHEL/CentOS 7上设置用于多个Linux发行版安装的“PXE网络启动服务器“
    在IDEA中如何使用tomcat部署项目
    推荐系统-排序层-特征工程:用户特征、物品特征
    第3.6章:StarRocks数据导入——DataX StarRocksWriter
  • 原文地址:https://blog.csdn.net/m0_58679504/article/details/126027147