我在java认证网站中发现了这段代码
public class Test1{
public static void main(String args[]){
System.out.println(method());
}
public static int method(){
try{
return 1;
}
catch(Exception e){
return 2;
}
finally{
return 3;
}
}
}
因此,这段代码的输出显示为3。这怎么可能。。因为它在try块本身中返回1?代码永远不会最终到达,对吧??
代码永远不会到达最终目的地,对吗不,如果有一个最终阻止控制将转到尝试或/和捕获后的最终
因为在任何情况下,最终都会执行。除了Mike Kobit说的System.exit
感谢Jason C,来自JLS 14.17。退货声明
由此可见,return语句总是突然完成。
前面的描述说";试图转移控制权";而不仅仅是";转移控制权";因为如果方法或构造函数中有任何try语句(§14.20)的try块或catch子句包含return语句,那么在控制权转移到方法或构造函数的调用程序之前,这些try语句的任何finally子句都将按从内到外的顺序执行。finally子句的突然完成可能会中断由return语句发起的控制权转移。
来自JLS 14.20.2。执行try finally和try catch finally
如果try块的执行正常完成,则执行finally块,然后有一个选择:
- 如果finally块正常完成,则try语句正常完成
- 如果finally块由于原因S而突然完成,那么try语句则由于原因S突然完成
因此,在您的代码中,try返回1,然后控制转到finally,后者返回3。所以函数的返回值为3。
正如Sumit Singh在回答中提到的,发生这种情况是因为return
导致方法突然结束。
当您在try-catch finally块中抛出新的Exceptions时,您可以观察到同样的行为,因为throw
也是突然的。
请参阅以下代码:
public class FinallyTest {
public static void main(String[] args) {
abrupt();
}
@SuppressWarnings("finally")
public static void abrupt() {
try {
throw new IllegalArgumentException("In Try");
}
catch(Exception x) {
throw new IllegalArgumentException("In Catch");
}
finally {
throw new NullPointerException("In Finally");
}
}
}
运行代码时,控制台显示
Exception in thread "main" java.lang.NullPointerException: In Finally
at FinallyTest.abrupt(FinallyTest.java:15)
at FinallyTest.main(FinallyTest.java:3)
即使在try
块内抛出一个新的IllegalArgumentException
,也只抛出finally
块中的NullPointerException
,因为该块突然结束。
Finally块总是在执行return
语句之前执行。(也有一些例外,比如JVM本身崩溃或system.exit()
被调用)
原因如下:
我们通常使用finally来释放资源或进行清理。现在,若开发人员在try块中意外地编写了return语句,那个么从逻辑上讲,最终将永远不会被执行。为了克服这个问题,JVM自己处理这个场景,并在从try块返回之前执行finally块。
记住finally块总是在try块退出时执行。上面解释的场景也适用于返回、继续或中断。
因为如果我们考虑优先级finally
比try
或catch
多,为了清楚地表明,如果即使在最后执行时也没有捕捉到异常,并且它在方法内部工作,所以从逻辑上讲,当一个方法假设返回一个输出int
值时,它显然总是会返回finally
的值。
这有道理吗?