Groovy 异常传播是怎么处理的?

文章导读
Previous Quiz Next 异常传播指的是异常事件从嵌套的 try 块或嵌套的方法调用中传播的过程。一个 try 块可以嵌套在另一个 try 块中。同样,一个方法可以调用另一个方法,每个方法可以独立处理异常,或者抛出 checked/unchecked excep
📋 目录
  1. Java 中的异常传播规则
  2. 示例 - 异常传播
  3. 示例 - 异常向 JVM 传播
  4. 示例 - 停止异常传播
A A

Groovy - 异常传播



Previous
Quiz
Next

异常传播指的是异常事件从嵌套的 try 块或嵌套的方法调用中传播的过程。一个 try 块可以嵌套在另一个 try 块中。同样,一个方法可以调用另一个方法,每个方法可以独立处理异常,或者抛出 checked/unchecked exceptions。每当在嵌套的 try 块/方法中引发异常时,该异常会被推入 Stack。异常会从子 try 块传播到父 try 块,或者从子方法传播到父方法,依此类推。

语法 - 嵌套 Try 块

嵌套 catch 块的语法如下所示 −

try { // 父 try 块
   try {  // 子 try 块
   
   }
   catch(ExceptionType1 e1){  // 子 catch 块
   
   }
} catch (ExceptionType2 e1) { // 父 catch 块

} 

语法 - 嵌套方法调用

嵌套方法调用的语法如下所示 −

method1(){ // 父方法 
   try { // 父 try 块
      method2();
   } catch (ExceptionType2 e1) { // 父 catch 块
} 
method2(){ // 子方法 
   // 抛出异常的代码
   // 此异常将由父方法处理
} 

前面的语句演示了两个 try/catch 块和方法,但你可以有任意数量的它们。如果在受保护的子代码中发生异常,则异常会被抛到子列表的 catch 块中。如果抛出的异常的数据类型匹配 ExceptionType1,则在那里被捕获。如果不匹配,则异常会向上传递到父 catch 语句中。这一过程持续进行,直到异常被捕获,或者穿过所有 catch 块,在这种情况下,当前方法停止执行,异常被抛到调用栈上的前一个方法中。

Java 中的异常传播规则

  • 子 catch 块应使用特定的异常类型,以提高代码清晰度。父 catch 块可以处理更通用的异常,以便如果子 catch 块无法处理该异常,则父 catch 块可以处理它。

  • 子 catch 块与父 catch 块中使用的异常层次结构没有限制。

  • 如果子 catch 块正确处理了异常,则在父块中可以引发并处理另一个异常。

示例 - 异常传播

以下代码片段展示了异常事件从子方法传播到父方法的示例。在此示例中,我们在子方法中通过将一个值除以 0 来创建错误。子方法抛出异常。现在在父方法中,在 try 块内,我们处理该异常并打印错误消息。

Example.groovy

class Example {
   static void main(String[] args) {
      int a = 3;
      int b = 0;
      try {
         println("result:" + divide(a,b));
      }catch(ArithmeticException e) {
         println(e.getMessage());
      }
   }

   static int divide(int a, int b) {
      return a / b;
   }
}

输出

Division by zero

示例 - 异常向 JVM 传播

以下代码片段展示了从子方法向父方法传播异常事件。在本示例中,我们在子方法中通过将一个值除以 0 来制造错误。子方法抛出异常。现在在父方法中,我们不处理该异常。JVM 将拦截该异常并打印错误消息。

Example.groovy

class Example {

   static void main(String[] args) {
      int a = 3;
      int b = 0;
      println("result:" + divide(a,b));
   }

   static int divide(int a, int b) {
      return a / b;
   }
}

输出

Caught: java.lang.ArithmeticException: Division by zero
java.lang.ArithmeticException: Division by zero
	at Example.divide(Example.groovy:10)
at Example.main(Example.groovy:6)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)

示例 - 停止异常传播

以下代码片段展示了异常事件在子方法内部停止传播,而不是流向父方法。在本示例中,我们在子方法中通过将一个值除以 0 来制造错误。子方法处理了该异常。现在在父方法中,我们不会收到任何异常。

Example.groovy

class Example {
   static void main(String[] args) {
      int a = 3;
      int b = 0;
      println("result:" + divide(a,b));
   }

   static int divide(int a, int b) {
      try {
         return a / b;
      }catch(ArithmeticException e) {
         println(e.getMessage());
      }
   return 0;
   }
}

输出

Division by zero
result:0