Java中的异常传播
先决条件: Java中的异常,已检查与未检查的异常
异常传播:首先从栈顶抛出异常,如果没有被捕获,则将调用栈下拉到前一个方法。
在方法抛出异常后,运行时系统会尝试找到一些东西来处理它。处理异常的一组可能的“东西”是已调用的方法的有序列表,以获取发生错误的方法。方法列表称为调用堆栈,搜索方法是异常传播。
未经检查的异常中的异常传播
当异常发生时,传播是一个将异常从堆栈顶部丢弃到底部的过程。如果一次没有被捕获,异常会再次下降到前一个方法,依此类推,直到它被捕获或到达调用堆栈的最底部。这称为异常传播,这发生在未经检查的异常的情况下。
在下面的示例中,异常发生在未处理的 m() 方法中,因此将其传播到未处理的先前 n() 方法,再次传播到处理异常的 p() 方法。
异常可以在调用堆栈中的任何方法中处理,无论是 main() 方法、p() 方法、n() 方法还是 m() 方法。
注意:默认情况下,未经检查的异常在调用链中转发(传播)。
// Java program to illustrate
// unchecked exception propagation
// without using throws keyword
class Simple {
void m()
{
int data = 50 / 0; // unchecked exception occurred
// exception propagated to n()
}
void n()
{
m();
// exception propagated to p()
}
void p()
{
try {
n(); // exception handled
}
catch (Exception e) {
System.out.println("Exception handled");
}
}
public static void main(String args[])
{
Simple obj = new Simple();
obj.p();
System.out.println("Normal flow...");
}
}
输出:
Exception handled
Normal flow...
检查异常中的异常传播
与 Unchecked Exceptions 不同,Checked Exception 的情况下不会发生异常传播,并且在此处必须使用 throw 关键字。仅传播未经检查的异常。检查的异常抛出编译错误。
在下面的示例中,如果我们在 m() 和 n() 函数中省略 throws 关键字,编译器将生成编译时错误。因为与未经检查的异常不同,检查的异常在不使用 throws 关键字的情况下无法传播。
注意:默认情况下,检查的异常不会在调用链中转发(传播)。
// Java program to illustrate exception propagation
// in checked exceptions and it can be propagated
// by throws keyword ONLY
import java.io.IOException;
class Simple {
// exception propagated to n()
void m() throws IOException
{
// checked exception occurred
throw new IOException("device error");
}
// exception propagated to p()
void n() throws IOException
{
m();
}
void p()
{
try {
// exception handled
n();
}
catch (Exception e) {
System.out.println("exception handled");
}
}
public static void main(String args[])
{
Simple obj = new Simple();
obj.p();
System.out.println("normal flow...");
}
}
输出:
exception handled
normal flow...