35

我对java不熟悉,我最近一直在看一些同事写的一些让我困惑的代码。这是它的要点:

public response newStuff(//random data inside) {
    try {
       response or = //gives it a value
       log.info(or.toString());
       return or;
    }
    catch ( Exception e) {
        e.printStackTrace();
    }
    finally {
        return null;
    }
}

在这里添加 finally 块真的有什么意义吗?我不能只在 catch 块中添加 return null ,这将执行相同的行为,还是我错了?

4

10 回答 10

31

在这里添加 finally 块真的有什么意义吗?

对此的回答是一个响亮的“不”:return在块中放置一个语句finally是一个非常糟糕的主意。

我只是在 catch 块中添加 return null ,这将执行相同的行为,还是我错了?

它与原始行为不匹配,但这是一件好事,因为它会修复它。而不是null像原始代码那样无条件地返回,块return内部的代码只会在错误时返回。换句话说,除非出现异常,否则分支中返回的值将返回给调用者。catchnulltry

此外,如果您在块之后添加,return null catch将看到返回null异常的正确效果。我会更进一步,并return在方法中添加一个,如下所示:

response or = null;
try {
   or = //gives it a value
   log.info(or.toString());
} catch ( Exception e) {
    e.printStackTrace();
}
return or;
于 2013-10-21T15:27:55.100 回答
23

实际上,没有。finally (几乎)总是运行,无论 try-catch 块中的结果如何;所以这个块总是返回null。在这里,看看这个例子:

public class Finally {

/**
 * @param args
 */
public static void main(String[] args) {
    System.out.println(finallyTester(true));
    System.out.println(finallyTester(false));
}

public static String finallyTester(boolean succeed) {
    try {
        if(succeed) {
            return "a";
        } else {
            throw new Exception("b");
        }
    } catch(Exception e) {
        return "b";
    } finally {
        return "c";
    }
  }

}

它将两次打印“c”。

上述规则的例外情况是线程本身被中断;例如由System.exit(). 然而,这是一件罕见的事情。

于 2013-10-21T15:35:20.877 回答
5

finally无论如何都会执行,通常可以用来关闭会话等。不要将返回值放在 finally 块中。

于 2013-10-21T15:27:28.490 回答
4

这看起来是一个非常糟糕的做法。在这种情况下,您的代码将始终返回null.

finally块运行后最后调用该块try-catch。无论是否调用了try完成或块。exception在这种情况下,无论运行哪条代码路径,您都将始终返回 null。在“正常”情况下,您将 the 放在return nullfinally 之后,确实有机会返回某些东西(从 thetry或从catch块),如果没有流产生返回对象,您会退回到return null,但您并不总是返回空值。

于 2013-10-21T15:27:51.973 回答
4

我读过很多人只是简单地回答“不要return在 finally 块中使用”,而没有任何解释。好吧,实际上您发布的代码是一个很好的例子,其中return一个finally块中的 a 引起了巨大的混乱。甚至在撰写本文时,最受好评的答案弄错了即使有 Exception ,您的代码也将始终执行return null;as last 命令。

但是我可以想到return一个finally块中的 a 实际上是有意义的情况。在我看来,您的代码作者的目标是该方法从不抛出 a ,而是Throwable返回null。如果您像这样修改代码,这实际上可以实现:

public Result newStuff() {
    Result res = null;
    try {
       res = someMethod();
       log.info(res.toString());
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    finally {
        return res;
    }
}

但请注意,这不会调用printStackTrace()sErrorThrowable不是Exceptions 的 s。

于 2013-10-22T13:41:00.633 回答
3

无论“Catch”是否触发,“Finally”块都将执行。因此,行为与仅在 Catch 块中放入“return null”不同。

于 2013-10-21T15:27:52.897 回答
3

finally 块中应该没有return语句,remove return

于 2013-10-21T15:31:14.990 回答
2

finally 块的需要是当您有这样的代码时应该始终执行,例如您想要关闭输入流或者您想要关闭任何连接等。只需在谷歌上搜索此内容,您将很容易找到此示例。

在你的情况下,你正在编写一个方法,你在 try 块中返回一些东西,最后你正在编写 finally 块,你正在返回 null。我在这里看不到 finally 块的任何用途。

于 2013-10-21T15:34:43.693 回答
1

如果要执行某些语句,即使 try 块或 catch 块中的代码是否生成异常,也可以使用 finally 块。但是当您在 try 块中使用 return 时,将 return 放在 finally 块中没有意义。您可以直接从 catch 块返回,并且可以删除 finally 块。

于 2013-10-22T06:03:46.083 回答
1

首先了解初学者为什么需要这三个块。

1)try 块:如果您怀疑您的代码会导致异常,请放入 try 块

2)catch 块:如果出现异常,那么你需要执行的一段代码应该写在这个块中

3)finally 阻塞:如果你想让你的代码不管是否出现异常都被执行,那么我们去 finally 阻塞。该块主要用于释放资源。例如:

try{
   Connection conn=//something;
   //some code for database operations

}catch(SQLException e){
        e.printStackTrace()
}finally{
      conn=null;
}

无论结果如何,您都必须将连接设为空,因为它是重对象,如果被引用,则会在数据库上创建负载,因为只有少数连接对象可用。因此,最好的方法是让他们在 finally 块中。

在您的情况下,在 finally 块中返回 null 是不好的方法,因为无论是否出现异常,它都将始终返回 null 。

于 2013-10-22T10:36:53.253 回答