【问题标题】:Is it good practice to have return statement in try block when returned value from finally block is concerned当涉及到 finally 块的返回值时,在 try 块中使用 return 语句是否是一种好习惯
【发布时间】:2010-09-04 16:06:32
【问题描述】:

我想知道,从try 屏蔽return 是一种好习惯吗?

package debug;

/**
 *
 * @author Owner
 */
public class Main {

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

  static boolean cleanup() {
    // Fail to cleanup.
    return false;
  }

  static boolean fun() {
    boolean everything_is_fine = true;
    try {
      System.out.println("open file stream");
      return everything_is_fine;
    } finally {
      everything_is_fine = cleanup();
    }
  }
}

我首先想到false 会被打印出来。但是,这里是输出:

open file stream
true

如您所见,如果我在 try 块中有 return 语句,我将错过 finally 清理期间的失败状态。

我应该把代码写成:

  static boolean fun() {
    boolean everything_is_fine = true;
    try {
      System.out.println("open file stream");      
    } finally {
      everything_is_fine = cleanup();
    }
    return everything_is_fine;
  }

只要是finally块的返回值,是否应该避免try的return?

【问题讨论】:

  • 如有疑问,请以明确、直观的方式编写代码。

标签: java


【解决方案1】:

您建议的代码(在问题的末尾)很好。您可以finally 块返回,但不应该 - 例如 eclipse 显示警告“finally 块未正常完成”。

事实上,try/finallyreturn 没有直接关系。这里看起来是这样,因为它是方法中唯一的构造,但之后可以有其他代码(例如 - 事件通知),然后返回。

至于您的问题 - 如果 returned variablefinally 块中已返回,则您无法更改它的值。所以不要从try返回。

【讨论】:

  • @NullUserException 我的意思是另一件事,在问题的上下文中应该是完全可见的。但是,我改写了最后一句话,以便即使脱离问题的上下文也是如此。
【解决方案2】:

return 语句指示返回的值,在执行return 语句时是truefinally 确实改变了变量 everything_is_fine 的值,但这不会改变已经执行的 return 语句返回的内容。

可以finally 中添加另一个返回值,这将覆盖try 中的return

static boolean fun() {
    boolean everything_is_fine = true;

    try {
      System.out.println("open file stream");
      return everything_is_fine;
    } finally {
      everything_is_fine = cleanup();
      return everything_is_fine;
    }
  }

但是,使用finally 来修改控制流并不是一种好的做法。这当然是可能的。在您的情况下,这样做的更好方法是:

static boolean fun() {
    boolean everything_is_fine = true;

    try {
      System.out.println("open file stream");
    } finally {
      everything_is_fine = cleanup();
    }

    return everything_is_fine;
  }

顺便说一句,变量名应根据现行的Java naming conventions 更改为everythingIsFine ;-)

【讨论】:

    【解决方案3】:

    为什么返回“true”的答案:

    如果变量是从try返回的,虽然返回的变量值在finally块中改变了,但之前设置的值(在这种情况下是在try块中设置的值)将被返回。 (当然finally中没有return语句)

    回答您希望达到的目标:

    如果您希望更改要在 finally 块中返回的值,请遵循您的第二种方法。即:

     static boolean fun() {
        boolean everything_is_fine = true;
        try {
          System.out.println("open file stream");      
        } finally {
          everything_is_fine = cleanup();
        }
        return everything_is_fine;
      }
    

    【讨论】:

    • @NullUserException 请尝试相同并证明它。
    • 也有 finally 不总是执行的情况
    • @NullUserException 您正在显示的示例最终包含“return”语句。我的回答的意思是,如果变量是从尝试返回的,虽然最后这个变量的值发生了变化,但会返回更早的值。如果最终没有返回其他内容,则为offcourse。将更新我的答案。
    • @YoK 我不知道你的意思。我想不出使用try 块的返回值代替finally 块的返回值的方法。
    • @YoK 如果 OP 在 finally 块中有 return false,则该方法将返回 false。当然,如果finally 块中没有返回任何内容,它将使用最后一个返回(来自try 块的true
    【解决方案4】:

    虽然这被认为是不好的做法,但您可以返回finally。这样做也胜过您在trycatch 块中可能拥有的任何其他returns。证明:

    class Main
    {
        public static String test() {
            try {
                except();
                return "return from try";
            } catch (Exception e) {
                return "return from catch";
            } finally {
                return "return from finally";
            }
        }
    
        public static void except() throws Exception {
            throw new Exception();
        }
    
        public static void main(String[] args) {
            System.out.println(test());
        }
    }
    

    将打印“从最终返回”。在ideone 上查看。

    finally 块总是被执行(禁止调用System.exit() 或拔掉电源插头)

    编辑:请注意,在您的第一个代码示例中,finally 块中没有返回任何内容,但如果您在那里有一个 return false,您的方法将始终返回 false。

    【讨论】:

    • 虽然它可以从 finally 块返回,但我认为这不是一个好习惯。原因 finally 块的目的是“清理”。
    • @YoK 我也没有,我在回答中这么说。
    • 所以你的答案是不相关的,因为问题谈到了良好的做法。 finally 不会在比你说的更多的情况下被执行:如果执行 try 或 catch 代码的线程被中断或杀死
    • 这更像是一个评论而不是一个答案,但是太长了,不能放在评论中。
    • 所以你把评论放在答案部分?告诉我你希望我做什么?
    【解决方案5】:

    finally 块中对everything_is_fine 的赋值不会影响返回的内容。对我来说,这似乎是一种糟糕的做法。目的是什么?

    【讨论】:

      【解决方案6】:

      如果你需要返回依赖于 finally 块中运行的代码的东西,那么你需要把你的 return 放在 try 块之外;正如其他人所说,最好只有一个 return 声明。

      话虽如此,我从来没有遇到过我的返回值依赖于 finally 块中的计算的情况,我通常会将返回值放在 try 中。

      【讨论】:

        猜你喜欢
        • 2015-10-01
        • 1970-01-01
        • 2017-12-09
        • 2012-08-22
        • 1970-01-01
        • 2015-05-02
        • 1970-01-01
        • 2013-03-30
        • 1970-01-01
        相关资源
        最近更新 更多