这个概念出奇地在Java关于异常的教程页面中解释得很清楚。
异常会从方法传递到方法,沿着调用栈向上传递,直到被捕获。所以如果a()
调用了b()
,b()
又调用了c()
,c()
再调用了d()
,如果d()
抛出了异常,除非其中一个方法捕获了异常,否则异常将从d传播到c,然后传递到b,最后传递到a。
简短回答: 未捕获的异常会在调用堆栈上传播,直到堆栈变为空为止,这个过程称为异常传播。
详细回答: 当一个方法抛出异常后,运行时系统会在调用堆栈中搜索包含能够处理该异常的代码块(异常处理程序)的方法。搜索从发生错误的方法开始,并按方法被调用的相反顺序通过调用堆栈进行。当找到合适的处理程序时,运行时系统将异常传递给该处理程序。另外需要注意的一点是:
假设我们有一系列方法,其中method3() 调用 method2(),method2() 再调用 method1()。所以当
1) 在 method3() 中发生异常并且在 method3() 中没有任何异常处理程序。
2) 未捕获的异常将向下传播至stack,即它将在 method2() 中检查适当的异常处理程序。
3) 如果在 method2 中再次没有找到任何异常处理程序,则异常会向下传播到 method1(),在那里找到异常处理程序。
示例:
class ExceptionPropagation{
void method3(){
int result = 100 / 0; //Exception Generated
}
void method2(){
method3();
}
void method1(){
try{
method2();
} catch(Exception e){
System.out.println("Exception is handled here");
}
}
public static void main(String args[]){
ExceptionPropagation obj=new ExceptionPropagation();
obj.method1();
System.out.println("Continue with Normal Flow...");
}
}
输出:
异常在此处被处理
继续正常流程...
只有未检查的异常会传播。 检查的异常会抛出编译错误
[1] http://docs.oracle.com/javase/tutorial/essential/exceptions/definition.html
public class ExceptionTest {
public static void main(String[] args) {
method1();
System.out.println("after calling m()");
}
static void method1() {
method2();
}
static void method2() {
method3();
}
static void method3() {
throw new NullPointerException();
}
}
public class ExceptionTest {
public static void main(String[] args)
throws FileNotFoundException {
method1();
System.out.println("after calling m()");
}
static void method1() throws FileNotFoundException{
method2();
}
static void method2() throws FileNotFoundException{
method3();
}
static void method3() throws FileNotFoundException{
throw new FileNotFoundException();
}
}
来自:http://www.javamadesoeasy.com/2015/05/exception-propagation-in-java-deep.html
class MyClass{
void myMethod(){
A a = new A();
a.doSomething(0);
}
}
class A{
double doSomething(int n){
return 1/n;
}
}
myMethod
方法,将在对象A
的doSomething
方法中抛出异常,并将该异常传播到调用堆栈中的调用方法(因此在此示例中将该异常传播到myClass
的myMethod
)。