以下代码编译完美。我相信这是因为编译器在编译时知道控件将转到finally块并抛出未检查的异常(这是可以的,不需要处理),并且它知道在此之前代码抛出的所有其他异常都会丢失。所以不用担心他们。
try{
// DoSomething();
}catch(Exception e){
// Throw checked exception
}finally{
// Throw unchecked exception
}
示例:
public class TestClass {
public static void main(String[] args) {
TestClass c = new TestClass();
try {
// Whatever
} catch (Exception e) {
throw new FileNotFoundException();
} finally {
throw new NullPointerException();
}
}
}
到目前为止还不错,直到我从一个方法中抛出未检查的异常
try{
// DoSomething();
}catch(Exception e){
// Call a method that throws a checked exception
// or just throw the checked exception from here
}Finally{
// Call a method that throw an unchecked exception
}
示例:
public class TestClass {
public static void main(String[] args) {
TestClass c = new TestClass();
try {
//Whatever
} catch (Exception e) {
c.m1();
// or just throw it here
// throw new FileNotFoundException();
} finally {
c.m2();
}
}
public void m1() throws IOException {
throw new FileNotFoundException();
}
public void m2() throws RuntimeException {
throw new NullPointerException();
}
}
此代码不会编译。它用错误"未处理的异常类型_"(eclipse)或"未报告的异常_;必须捕获或声明为抛出"(cmd)标记c.m1()。
就好像它忽略了finally块将抛出LAST异常(未选中),并且无需担心catch块中的那个异常,即使它是未处理的已选中异常,因为它们无论如何都会丢失!知道m2()被声明为专门抛出未检查的异常(RuntimeException)。
有人能更好地解释为什么第二段代码中出现编译错误吗?感谢:)
异常只是不会"抛出"它们自己。您必须显式处理被调用方法抛出的任何已检查异常——无论它们发生在哪里。您调用的任何引发已检查异常的对象都必须被try-catch块包围,或者调用子方法的方法必须声明以引发相同类型的异常。这不适用于已检查的异常。
这意味着,在你有的地方
catch (Exception e) {
c.m1();
// or just throw it here
// throw new FileNotFoundException();
}
您必须捕获m1
抛出的已检查异常,因为main
没有声明它抛出任何东西。
在try/catch上有finally
块的情况下,您仍然必须处理被调用方法抛出的任何已检查异常——即使是在catch块中。但是,如果您使用显式抛出运行时异常的finally块显式抛出已检查的异常,编译器会允许它,因为它可以确定事件的顺序——在任何情况下,在任何时间。