【问题标题】:Returning a value from a finally block [duplicate]从finally块返回一个值[重复]
【发布时间】:2015-06-14 08:42:51
【问题描述】:

我在一个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 ? 代码永远不会到达finally吧??

【问题讨论】:

标签: java try-catch-finally


【解决方案1】:

代码永远不会到达 finally 对吗? 不,如果有 finally 块控制将在 try 或/和 catch 之后转到 finally

因为无论如何 finally 都会执行。除非 Mike Kobit 说System.exit

感谢 Jason C,来自 JLS 14.17. The return Statement

可以看出,return 语句总是突然完成。

前面的描述说“尝试转移控制”,而不仅仅是“转移控制”,因为如果方法或构造函数中有任何 try 语句(第 14.20 节),其 try 块或 catch 子句包含 return 语句,那么任何 finally这些 try 语句的子句将按从内到外的顺序执行,然后将控制权转移到方法或构造函数的调用者。 finally 子句的突然完成可能会中断由 return 语句启动的控制转移。

来自JLS 14.20.2. Execution of try-finally and try-catch-finally

如果try块的执行正常完成,则执行finally块,然后有一个选择:

  1. 如果 finally 块正常完成,则 try 语句正常完成。
  2. 如果 finally 块由于原因 S 突然完成,则 try 语句由于原因 S 突然完成。

所以在你的代码中尝试返回1,然后控制最终返回3。所以函数的返回值将是3。

【讨论】:

  • 嗯,几乎总是这样。 Certain cases(如System.exit)不会。
  • 但是有可能return 来自try 块的值吗?似乎答案是否定的。
  • @MikeKobit 感谢您的加入。
  • try 阻塞 return 值 1 在调用堆栈中的哪个位置?
  • @TimBiegeleisen 不,如果你也从 finally 返回一些东西。
【解决方案2】:

Finally 块总是在return 语句被执行之前被执行。 (有一些异常,比如JVM本身crash或者system.exit()被调用)

原因如下:

我们通常使用 finally 来释放我们的资源或进行清理。现在,如果开发人员会在 try 块中意外写入 return 语句,那么逻辑上 finally 将永远不会被执行。为了克服这个问题,JVM 自己处理这种情况,并在从 try 块返回之前执行 finally 块。

记住 finally 块总是在 try 块退出时执行。上述场景也适用于返回、继续或中断

【讨论】:

    【解决方案3】:

    正如 Sumit Singh 在他的回答中提到的,发生这种情况是因为 return 导致方法突然结束。

    当您在 try-catch-finally 块中抛出新异常时,您可以观察到相同的行为,因为 throw 也是 abrupt

    见以下代码:

    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,因为该块突然结束。

    【讨论】:

      【解决方案4】:

      因为如果我们考虑优先级finallytrycatch 更多,要清楚如果即使在finally 执行时异常还没有捕获到这里它在一个方法中工作,逻辑上如此当假设方法返回单个输出 int 值时,显然它将始终返回来自 finally 的值。

      有意义吗?

      【讨论】:

      • 但是既然在try块中,它是返回一个值,为什么它还要去执行finally呢?
      • @AqeelSmith 因为这正是finally 的意义所在:无论发生什么,最终都会被执行。它通常用于清理,例如.close()ing 的东西。
      • 这个我还是不是很清楚!
      • 因为只是为了您的理解目的而不是非常技术性,请记住优先级finallytrycatch 更多所以无论尝试是否有效,最终都会赢得比赛跨度>
      猜你喜欢
      • 1970-01-01
      • 2013-06-28
      • 2010-09-08
      • 2017-07-20
      • 1970-01-01
      • 2015-02-16
      相关资源
      最近更新 更多