java - 为什么Exception.fillInStackTrace返回Throwable?

标签 java exception-handling throwable

我认为Exception.fillInStackTrace应该返回Exception或派生的Exception对象。考虑以下两个功能,

public static void f() throws Throwable {
    try {
        throw new Throwable();
    } catch (Exception e) {
        System.out.println("catch exception e");
        e.printStackTrace();
    } 
}
public static void g() throws Throwable {
    try {
        try {
            throw new Exception("exception");
        } catch (Exception e) {
            System.out.println("inner exception handler");
            throw e.fillInStackTrace();
        }
    } catch (Exception e) {
        System.out.println("outer exception handler");
        e.printStackTrace();
    }
}
  • 在第一个函数exception handler中,new Throwable()无法捕获f()
  • exception handler可以在第二个函数e.fillInstackTrace()中捕获g()
  • 但是第二个函数g()仍然需要throws Throwable。这真的很奇怪,因为我们可以捕获e.fillInstackTrace()

  • 所以我的问题是,为什么Exception.fillInStackTrace不返回Exception或Exception派生,而不是开发出这种奇怪的语法?

    编辑:
    为了澄清我的问题:我所说的“奇怪的语法”是
  • 由于Exception.fillInStackTrace()返回Throwable引用,因此接收Exception引用的异常处理程序应该无法捕获该异常。由于java不允许隐式向下转换,因此它应该类似于return (Exception)e.fillInstackTrace()
  • 由于已设计为接受Exception引用的异常处理程序可以处理Throwable异常,因此无需标记g()方法引发Throwable异常。但是Java编译器会强制我们这样做。

  • 谢谢。

    最佳答案

    从问题2开始回答问题实际上更容易。

    您询问:
    2.由于接收到Exception引用的异常处理程序被设计为可以处理Throwable异常,因此无需标记g()引发Throwable异常的方法。但是Java编译器会强制我们这样做。

    回答:
    实际上,catch(异常e)不能捕获Throwable。
    试试这个:

    try {
           Throwable t = new Throwable();
           throw t.fillInStackTrace();
    } catch (Exception e) {
        System.out.println("outer exception handler");
        e.printStackTrace();
    } 
    

    您会看到在这种情况下catch子句不会捕获throw。

    catch子句在您的g()方法中起作用的原因是,当您调用throw e.fillInStackTrace()时,对fillInStackTrace的调用实际上返回一个Exception(这是因为e本身就是一个Exception)。由于Exception是Throwable的子类,因此不与fillInStackTrace的声明相矛盾。

    现在开始第一个问题

    您询问:
    1.由于Exception.fillInStackTrace()返回Throwable引用,因此接收到Exception引用的异常处理程序应该无法捕获该异常。由于Java不允许隐式向下转换,因此它应类似于return(Exception)e.fillInstackTrace() 。

    回答:
    这不完全是隐式的垂头丧气。可以认为这是过载的一种变化。

    假设您有
    void process(Throwable t){
       ...
    }
    void process(Exception e){
      ...
    } 
    

    如果调用process(someObject),则将在运行时确定是调用第一个还是第二个处理方法。同样,catch(Exception e)子句是否可以捕获您的throw,将在运行时根据您是否抛出Exception或Throwable来确定。

    关于java - 为什么Exception.fillInStackTrace返回Throwable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2025649/

    相关文章:

    java - 如何使用 Spring Data 将任意数据的子文档持久化到 MongoDB?

    java - 为什么需要 gwt-bootstrap?

    java - GZIP Streams 的序列化/反序列化不一致

    java - 如何获取抛出异常的方法名?

    java - 编写异构集合时可以避免适配器类吗?

    java - 如何使用 POI 锁定 Excel 工作表中的数据,使单元格没有任何数据/工作表的其余部分未锁定

    spring-boot - 错误页面注册器和全局异常处理

    c# - 最后在 C# 中阻塞

    c++ - 初学者如何处理用户输入类型不正确引起的异常

    java - 打印堆栈跟踪,包括已完成的方法