异常向上传播调用堆栈

sl1*_*133 4 java exception try-catch

我很难完全理解异常在调用堆栈中传播的概念或真正的用处。我知道如何创建它们,但我真的不知道它们何时会被使用,例如在简单的现实世界数学应用程序或其他应用程序中。

public void method1(){
    try{
        method2();
    }
    catch(Exception e){
        e.printStackTrace();
    }
}

public void method2(){
      try{
          throw new Exception();
      }
      finally{
         System.out.println("no exception, try cleanup");
      }
}
Run Code Online (Sandbox Code Playgroud)

我知道这基本上就是它的工作方式,尽管它可能会更多地涉及更多异常和函数,但我并没有真正理解使用这些而不是只在每个函数中捕获的意义。

Ste*_*n C 5

...但我真的不明白使用这些而不只是在每个函数中捕获的意义。

关键是调用堆栈上的下一个函数可能不知道如何处理异常。例子:

public class Test {

    public Object doSomething(String source) throws IOException {
        try (InputStream is = openAsStream(source)) {
            // ... read and process stuff
            return ...
        }
    }

    public InputStream openAsStream(String name) throws IOException {
        String fileName = // ... do something with 'name'
        return new FileInputStream(name);
    }

    public static void main(String[] args) {
        // ...
        Test t = new Test();
        try {
            t.doSomething(args[0]);
        } catch (IOException ex) {
            System.err.println("Cannot handle '" + args[0] + "'");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

调用构造openAsStream函数FileInputStream可能会抛出一个IOException. 该openAsStream方法无法从中恢复,因此让它传播。该doSomething方法也不知道如何处理它,因此它允许它传播。最后,异常到达main...,它知道如何向用户解释问题。


现在您可以编写openAsStream捕获IOException、打印错误消息并返回null. 但这将是一个很大的错误:

  • 他们openAsStream()不(也不应该)知道是否/如何向用户报告问题。

  • 如果它返回 anull给调用者,那么调用者必须测试调用的结果是否是null......并采取替代操作。

关键是方法应该只处理可以在该级别充分处理的异常。应该允许其他人传播。(或者可能包含在另一个异常中......如果这是 API 设计所需要的。)