我认为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/