从java.lang.Exception
类的javaDocs中:
如果方法或构造函数在执行过程中可能抛出已检查异常并且在方法或构造函数边界外传播,则需要在其throws子句中声明已检查异常。
但考虑以下代码:
package other;
public class CheckedExceptionHandling {
private static <E extends Exception> void throwException() throws E {
throw (E) new CheckedException2(); // unchecked cast warning
}
private static void setUncaughtExceptionHandler() {
Thread.currentThread().setUncaughtExceptionHandler((t, e) -> {
System.out.println("Unhandled exception: " + e.getClass()); // reports CheckedExceptionHandling$CheckedException2
});
}
public static void main(String[] args) /* no checked exceptions declared! */ {
setUncaughtExceptionHandler();
try {
CheckedExceptionHandling.<CheckedException1>throwException();
} catch (CheckedException1 e) {
System.out.println(e); // never gets here
}
}
// checked exceptions:
public static class CheckedException1 extends Exception {}
public static class CheckedException2 extends Exception {}
}
编译时出现一个警告,运行结果如下:
未处理的异常: class other.CheckedExceptionHandling$CheckedException2
我期望会出现以下一种情况:编译时错误 未报告的异常 CheckedException2; 必须捕获或声明为抛出
或者 不兼容类型: CheckedException2 无法转换为 CheckedException1
至少在运行时出现 ClassCastException
。
但是,编译器允许检查异常未被处理、未被声明并且传播到方法 main
的未捕获异常处理程序之外。
为什么?难道我漏掉了什么吗?
CheckedException2
转换为CheckedException1
,你的throwException()
声明它会抛出一个CheckedException1
,你的代码也捕获了一个CheckedException1
- 所以这不会是一个编译时错误。然而,当使用泛型时,将(E) new CheckedException2()
强制转换为CheckedException1
会产生一些严重的影响,这在Tunaki提供的链接中有描述。 - nos