Day42--异常向上抛出

Day42--异常向上抛出

  1. 方法调用栈的概念

    • 在Java程序执行过程中,方法之间会相互调用,当一个方法调用另一个方法时,就会形成一个方法调用栈。栈底是main方法(程序的入口),随着方法的调用,新的方法被压入栈顶。例如,main方法调用methodAmethodA又调用methodB,那么此时栈顶是methodB,中间是methodA,栈底是main方法。
  2. 异常向上层抛出的过程

    • 当在一个try块中发生异常,并且没有合适的catch块来处理这个异常时,异常会沿着方法调用栈向上传播。也就是说,异常会从当前方法抛出,回到调用该方法的上层方法中。
    • 例如,假设有三个方法method1method2method3method3在执行过程中出现了异常,并且没有处理这个异常,那么这个异常会从method3抛出,回到调用method3method2中。如果method2也没有处理这个异常,异常会继续向上传播到调用method2method1中,以此类推,直到异常被处理或者到达main方法。如果异常一直传播到main方法都没有被处理,那么程序就会终止,并在控制台打印出异常信息。
  3. 示例代码说明

    • 假设有以下代码结构:
    public class ExceptionPropagation {
        public static void method3() {
            int[] arr = {1, 2, 3};
            System.out.println(arr[3]); // 这里会抛出ArrayIndexOutOfBoundsException异常
        }
        public static void method2() {
            method3();
        }
        public static void method1() {
            try {
                method2();
            } catch (ArithmeticException e) {
                System.out.println("捕获到ArithmeticException");
            }
        }
        public static void main(String[] args) {
            method1();
        }
    }
    
    • 以下是结合上述代码详细说明在方法调用栈中各个调用方法的位置所在以及位置变化情况:

      初始状态

      程序从 main 方法开始执行,此时方法调用栈中只有一个元素,即 main 方法处于栈底位置,此时栈的情况如下:

      栈内位置 方法名
      栈底 main

      main 方法调用 method1

      当执行到 main 方法里调用 method1 的语句时,method1 方法被压入栈中,此时 method1 位于栈顶,main 方法在栈底,调用栈结构变为:

      栈内位置 方法名
      栈顶 method1
      栈底 main

      method1 调用 method2

      method1 方法内部执行调用 method2 的语句后,method2 方法被压入栈顶,此时栈内从上到下依次是 method2method1main,结构如下:

      栈内位置 方法名
      栈顶 method2
      中间 method1
      栈底 main

      method2 调用 method3

      接着,method2 方法里调用 method3method3 会被压入栈顶,此时栈内元素顺序变为 method3 在最顶部,然后依次是 method2method1main,具体如下:

      栈内位置 方法名
      栈顶 method3
      第二层 method2
      第三层 method1
      栈底 main

      method3 中抛出异常后

      method3 方法执行到 System.out.println(arr[3]); 抛出 ArrayIndexOutOfBoundsException 异常时,由于 method3 本身没有处理这个异常,异常开始沿着方法调用栈向上传播。此时 method3 的执行会立即停止,它依然处于栈顶位置,但即将要被弹出栈,栈的情况暂时还是:

      栈内位置 方法名
      栈顶 method3
      第二层 method2
      第三层 method1
      栈底 main

      异常传播到 method2

      随着异常向上传播,method3 会被弹出栈(因为它已经执行不下去了,且异常要传递给上层方法),此时 method2 成为栈顶,栈内剩下 method2method1main,结构如下:

      栈内位置 方法名
      栈顶 method2
      第二层 method1
      栈底 main

      不过因为 method2 同样没有处理该异常的代码,它也没办法继续执行下去,同样即将被弹出栈,异常继续向上传播。

      异常传播到 method1

      method2 被弹出栈后,method1 变为栈顶,此时栈内只有 method1main,如下:

      栈内位置 方法名
      栈顶 method1
      栈底 main

      method1 里的 catch 块是用来捕获 ArithmeticException 的,无法捕获当前的 ArrayIndexOutOfBoundsException 异常,所以 method1 也执行不下去了,会被弹出栈,异常继续往 main 方法传播。

      异常传播到 main 方法时

      method1 被弹出栈后,此时整个方法调用栈中就只剩下 main 方法了,它既是栈顶也是栈底,栈的结构变为:

      栈内位置 方法名
      栈顶(也是栈底) main

      由于 main 方法也没有处理这个异常的代码,程序最终会因为这个未处理的异常而终止运行,此时方法调用栈也就随之销毁了。

      总之,在方法调用及异常传播过程中,方法调用栈会动态变化,新调用的方法会被压入栈顶,当出现异常且方法无法处理时,方法会从栈顶依次弹出,异常不断向上层方法所在的栈位置传播,直到被处理或者导致程序终止,栈中元素的这种变化顺序体现了方法间的调用关系以及异常回溯的过程。

异常会向上层抛出,指的是异常对象本身从当前抛出异常的方法位置,沿着调用栈的层次结构,依次回到调用它的上层方法中。

这个疑问的来源:

解释 Java 中的异常处理机制,包括try-catch-finally语句块的执行流程。

  • 首先执行try块中的代码,如果在try块中没有发生异常,则跳过catch块,直接执行finally块(如果有finally块),然后继续执行try-catch-finally语句块之后的代码。
  • 如果在try块中发生了异常,则立即停止try块中剩余代码的执行,根据异常的类型去匹配catch块中的异常类型,如果匹配成功,则执行对应的catch块中的代码,处理完异常后,再执行finally块(如果有)。如果没有匹配到合适的catch块,则异常会向上层抛出,直到被处理或者导致程序终止。
  • finally块中的代码无论是否发生异常都会被执行,通常用于释放资源等操作,如关闭文件流、数据库连接等,哪怕try块中使用了return语句,finally块依然会执行,并且如果finally块中有return语句,会覆盖trycatch块中的return结果哦(这是个容易混淆的点,也可以提及一下)。
    你上面说的“如果没有匹配到合适的catch块,则异常会向上层抛出”,这是啥意思?什么叫向上层抛出
posted @ 2024-12-07 21:58  1hahahahahahahaha  阅读(67)  评论(0)    收藏  举报