Groovy - 异常传播
异常传播指的是异常事件从嵌套的 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