什么是异常传播?

19
什么是异常传播?我试着在谷歌上搜索,但没有找到令人满意的结果。最好用Java解释一下。

这个问题有什么问题吗?为什么被踩了? - Paritosh Piplewar
@亲爱的:负分意味着(如工具提示所示)“没有显示任何研究努力”。考虑到nes1983的答案,这似乎是有道理的。 - Nicol Bolas
@home:背景(语言对异常处理的支持的另一个优点是异常传播)。 - Paritosh Piplewar
我没有点踩,但正如我在之前的评论中所述,你的问题有点太模糊了。 - home
1
你可以查看这个链接:https://dev59.com/UXA65IYBdhLWcg3w8zft - richardtz
显示剩余4条评论
7个回答

24

这个概念出奇地在Java关于异常的教程页面中解释得很清楚。

异常会从方法传递到方法,沿着调用栈向上传递,直到被捕获。所以如果a()调用了b()b()又调用了c()c()再调用了d(),如果d()抛出了异常,除非其中一个方法捕获了异常,否则异常将从d传播到c,然后传递到b,最后传递到a。


16

简短回答: 未捕获的异常会在调用堆栈上传播,直到堆栈变为空为止,这个过程称为异常传播。

详细回答: 当一个方法抛出异常后,运行时系统会在调用堆栈中搜索包含能够处理该异常的代码块(异常处理程序)的方法。搜索从发生错误的方法开始,并按方法被调用的相反顺序通过调用堆栈进行。当找到合适的处理程序时,运行时系统将异常传递给该处理程序。另外需要注意的一点是:

假设我们有一系列方法,其中method3() 调用 method2(),method2() 再调用 method1()。所以当

1) 在 method3() 中发生异常并且在 method3() 中没有任何异常处理程序。

2) 未捕获的异常将向下传播至stack,即它将在 method2() 中检查适当的异常处理程序。

3) 如果在 method2 中再次没有找到任何异常处理程序,则异常会向下传播到 method1(),在那里找到异常处理程序。

enter image description here

示例:

 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

[2] http://www.c4learn.com/java/java-exception-propagation/


7
每当方法被调用时,都会形成一个堆栈,异常首先从堆栈顶部抛出,如果未被捕获,则开始向下传递到先前的方法,直到被捕获为止。 如果异常即使到达堆栈底部仍未被捕获,则会传播到JVM并终止程序。 在Java中,未经检查的异常会自动传播。 程序>
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();
}

}

为了传播已检查的异常,方法必须使用throws关键字抛出异常。 程序>
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();
}

}

传播未检查的异常(NullPointerException) 传播已检查的异常(FileNotFoundException)使用 throws 关键字

来自:http://www.javamadesoeasy.com/2015/05/exception-propagation-in-java-deep.html


1
当出现异常时,传播是一个过程,在这个过程中,异常从堆栈的底部向上一直传递到顶部,并沿着调用链传递,如果在其中没有被捕获,异常会再次下降到先前的方法中,以此类推,直到它被捕获或者达到调用堆栈的最底部。这被称为异常传播。
例如,假设我们的堆栈是:
c()
b()
a()
main()
如果在c()方法中发生异常并且没有处理,它将传播到上一个b()方法,如果在那里没有处理,它将再次传播到a()方法,在那里异常被处理,以此类推。
异常可以在调用堆栈中的任何方法中处理,无论是在main()方法、a()方法、b()方法还是c()方法中。
回复线程

0
假设您有一个对象调用另一个对象,然后该对象调用另一个对象。如果在任何被调用的对象中抛出异常并且未被捕获,则异常会传播到调用方法(如果未在任何地方捕获,则会导致应用程序崩溃)。
class MyClass{

 void myMethod(){
   A a = new A();
   a.doSomething(0);
 }

}

class A{

  double doSomething(int n){
   return 1/n;
  }

}

如果执行myMethod方法,将在对象AdoSomething方法中抛出异常,并将该异常传播到调用堆栈中的调用方法(因此在此示例中将该异常传播到myClassmyMethod)。

0
如果需要此功能或何时使用它是问题的情况,这将回答此功能的目的。
在几件事情中,异常回溯沿着方法调用层次结构返回,启用了概念@transaction,这是使用面向方面编程概念自动启用的。 (@transaction有助于在Spring框架中回滚DB)。在您的调用层次结构中,异常传播直到声明@transaction的方法是必须的,以自动触发DB回滚,稍后您可以处理异常。与问题无关,但@transaction仅适用于运行时异常。

0
在构建程序时,错误发生的地方并不是处理它的最佳位置,即错误应该在其发生的地方而不是处理它的地方进行处理。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接