Sam*_*Sam 24 java exception-handling try-catch-finally
我有一个程序如下:
public class Main {
public static void main(String[] args)throws Exception
{
int res = test();
System.out.println("after call , res = " + res) ;
}
public static int test()throws Exception
{
try
{
return 10/0;
}
finally
{
System.out.println("finally") ;
}
}
}
Run Code Online (Sandbox Code Playgroud)
运行以上程序后,在控制台中看到以下结果:
finally
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.test(Main.java:17)
at Main.main(Main.java:7)
Run Code Online (Sandbox Code Playgroud)
这种行为是正常的,因为抛出到main方法的异常.
然后我改变代码如下:
public class Main {
public static void main(String[] args)throws Exception
{
int res = test();
System.out.println("after call , res = " + res) ;
}
public static int test()throws Exception
{
try
{
return 10/0;
}
finally
{
System.out.println("finally") ;
return 20;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在程序上面运行时,我在控制台中看到以下结果:
finally
after call , res = 20
Run Code Online (Sandbox Code Playgroud)
我的问题与第二种格式有关.为什么在finally块中返回时,异常没有抛到main方法?
bvd*_*vdb 13
抛出异常时,它将首先通过您的finally块.
如果您的finally块没有返回或抛出任何内容,则会传递原始异常.
finally另一方面,如果您的块返回一个值,则该异常将不再传播.
最后看一下try catch的执行情况.
如果V的运行时类型与try语句的任何catch子句的可捕获异常类不兼容,则执行finally块.然后有一个选择:
如果finally块正常完成,那么try语句会因为抛出值V而突然完成.
如果finally块由于原因S而突然完成,则try语句突然完成,原因是S(并且丢弃并抛弃了值V的抛出).
来自JLS(强调我的):
如果由于抛出值V而突然完成try块的执行,则有一个选择:
[...]
如果V的运行时类型不与任何catch子句的可捕获异常类分配兼容try语句,然后执行finally块.然后有一个选择:
如果finally块正常完成,那么try语句会因为抛出值V而突然完成.
如果finally块由于原因S而突然完成,则try语句突然完成,原因是S(并且丢弃并抛弃了值V的抛出).
这意味着如果你return在finally块中,该方法返回而不抛出异常.
此外return,还有其他状态因素可能导致finally阻止突然完成并忘记异常.它们在JLS第14.1节中定义.基本上,它是break,continue,return或者一个异常(或者由语句/方法引发或引起的).然后完整的try/catch/finally块以此原因完成.
在规范中还有一些更多的情况try/catch/finally,特别是如果没有异常或存在匹配的catch子句.它归结为finally节奏catch节拍try.