【问题标题】:Try , finally execution flow when return is in try block当 return 在 try 块中时 Try , finally 执行流程
【发布时间】:2015-01-22 22:16:44
【问题描述】:

try 时使用 finally 组合,在 try 中如果有 return 语句,为什么会先执行 finally 块?


class Palindrome
{
    public static void main(String args[]) 
    { 
        System.out.println(Palindrome.test()); 
    }

    public static int test()
    {
        try {  
                //return 0;  
                return 100;
        }  
        finally {  
            System.out.println("finally trumps return.");
        }
    }
}

在上面的代码中请告诉我执行的流程。我知道 finally 将在 try 块之后强制执行。但是在 try 块中,return 语句会将控制权交给主类。那样的话,控件怎么会最终阻塞呢?

【问题讨论】:

  • 您可以通过更少的努力手动验证它
  • @JigarJoshi:你如何验证“为什么”的问题?
  • 如果你进入 try 块,finally 块总是会被执行。这是规则。
  • 如果您想知道如何,请转储字节码。

标签: java return try-catch finally


【解决方案1】:

“第一”是什么意思?

finally 在执行离开方法之前运行。它还应该在什么时候运行?毕竟,它是方法的一部分。

如果你有

int x = 1;
try{
   return x;
} finally {
   x = x + 1;
}

那么该方法仍将返回 1。因此,return 语句确实会在 finally 块之前以某种方式执行(以确定返回值)。

如果问题是为什么要执行 finally 块根本,那么这就是它们的用途:在“try”块完成后“最终”运行,不管什么

但是在 try 块中,return 语句会将控制权交给主类。那样的话,控件怎么会最终阻塞呢?

怎么样?好吧,这就是语言(和运行时)的工作方式。

在控制流返回到调用方法之前,finally块被执行。

从技术上讲,它甚至可以选择更改返回值(通过拥有自己的 return 语句),但非常不鼓励这样做。

【讨论】:

  • 在我的代码中,从main方法开始,控件直接进入finally块。但不要进入尝试块。我对执行流程感到困惑。理想情况下,当 return 语句在 try 块中时,控件应该移出 try 块吗?
  • 它首先进入try 块。这就是该方法返回100 的原因。这个数字还会从哪里来?在return 之前放置另一个println。它将在 finally 块中的那个之前打印。
  • 感谢我正在寻找的答案 - 在控制流返回到调用方法之前,执行 finally 块
  • 上述代码的输出最终是胜过回报。 100 我的问题是为什么要在 try 块之前打印 finally 块中的 SOP。
  • 您的 try 块中没有打印。您从调用方法打印(这发生在方法返回之后,在 finally 块之后)。
【解决方案2】:

来自https://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html

finally block 是设计为始终执行:

finally 块总是在 try 块退出时执行。这 确保即使出现意外情况也会执行 finally 块 发生异常。但 finally 不仅仅对异常有用 处理 - 它允许程序员避免清理代码 意外地被返回、继续或中断绕过。进行清理 finally 块中的代码始终是一个好习惯,即使没有 预计会有例外情况。

如果你在 try 块中返回并且 finally 块中的代码没有被执行,这不是“总是执行”。

如果我们在 finally 块中做一些必要的事情,比如解锁锁、清理资源,这会使代码更具可读性,这会阻止其他一些新程序员(或您自己)在 try 块中添加一些返回或引入异常但没有清理资源的代码.

public static void main(String[] args) throws IOException {
    InputStream is;
    try {
        is = getInpustStreamFromNetwork();
        int i = 1 / 0;// 1. Intruduces exceptions
        return;// 2. returns before clean up resources
    } finally {
        is.close();// clean up resources is important, so it is a good practice to put it into finally block even though there is no exceptions to catch.
        System.out.println("no matter #1 or #2 ,this will be executed\n,");
    }
}

【讨论】:

    【解决方案3】:

    因为这是 finally 块的定义。无论块如何退出,它总是会发生。 finally 块用于应该始终执行的操作,例如关闭打开的流和清理套接字连接。无论块如何退出,都应该始终执行 finally 块中的代码。如果你想在 try 块成功退出的情况下跳过代码,那么它属于具有适当异常类型的 catch() 块。

    【讨论】:

      【解决方案4】:

      来自https://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html

      finally 块总是在 try 块退出时执行。这 确保即使出现意外情况也会执行 finally 块 发生异常。但 finally 不仅仅对异常有用 处理——它允许程序员避免清理代码 意外地被返回、继续或中断绕过。进行清理 finally 块中的代码始终是一个好习惯,即使没有 预计会有例外情况

      在某些情况下,finally 块可能无法执行。点击链接查看它们是什么。

      因此,您的问题的答案是设计使然。 Java 旨在以这种方式工作。

      【讨论】:

      • 感谢您的回答,这个设计是否涉及任何设计模式?
      • 你什么都不做。这就是 SUn now Oracle 设计该语言的方式。
      猜你喜欢
      • 2010-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-20
      • 2021-05-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多