问:

考虑到这段代码,我是否可以绝对确定 finally 块始终执行,无论 something() 是什么?

try {

something();

return success;

}

catch (Exception e) {

return failure;

}

finally {

System.out.println("I don't know if this will get printed out");

}

答1:

huntsbot.com汇聚了国内外优秀的初创产品创意,可按收入、分类等筛选,希望这些产品与实践经验能给您带来灵感。

是的,finally 将在 try 或 catch 代码块执行后被调用。

唯一不会调用 finally 的时间是:

如果调用 System.exit() 如果调用 Runtime.getRuntime().halt(exitStatus) 如果 JVM 先崩溃 如果 JVM 在 try 或catch 块 如果 OS 强制终止 JVM 进程;例如,在 UNIX 上 kill -9 如果主机系统死机;例如,电源故障、硬件错误、操作系统恐慌等如果 finally 块将由守护线程执行并且所有其他非守护线程在 finally 被调用之前退出

实际上 thread.stop() 并不一定会阻止 finally 块被执行。

不如说finally 块将在try 块之后 被调用,而before 控制权传递给以下语句。这与涉及无限循环的 try 块一致,因此 finally 块实际上从未被调用。

还有另一种情况,当我们使用嵌套的 try-catch-finally 块时

此外,如果守护线程抛出异常,也不会调用 finally 块。

@BinoyBabu - 这是关于终结器,而不是 finally 块

答2:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

示例代码:

public static void main(String[] args) {

System.out.println(Test.test());

}

public static int test() {

try {

return 0;

}

finally {

System.out.println("something is printed");

}

}

输出:

something is printed.

0

仅供参考:在 C# 中,除了不允许将 finally 子句中的语句替换为 return 2; 之外,行为是相同的(编译器错误)。

以下是需要注意的重要细节:stackoverflow.com/a/20363941/2684342

您甚至可以在 finally 块本身中添加一个 return 语句,然后它将覆盖先前的返回值。这也神奇地丢弃了未处理的异常。此时,您应该考虑重构您的代码。

这并不能真正证明最终王牌回归。返回值是从调用者代码中打印出来的。似乎证明不了多少。

对不起,但这是一个演示而不是证明。如果您可以证明此示例在所有 Java 平台上总是以这种方式运行,并且类似的示例也总是以这种方式运行,那么这只是一个证明。

答3:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

此外,虽然这是不好的做法,但如果 finally 块中有 return 语句,它将胜过常规块的任何其他 return。也就是说,以下块将返回 false:

try { return true; } finally { return false; }

从 finally 块中抛出异常也是如此。

这是一个非常糟糕的做法。请参阅 stackoverflow.com/questions/48088/…,了解有关它为什么不好的更多信息。

同意。 finally{} 中的返回会忽略 try{} 中抛出的任何异常。害怕!

@dominicbri7 为什么你认为这是一个更好的做法?当函数/方法无效时,为什么会有所不同?

出于同样的原因,我从不在我的 C++ 代码中使用 goto。我认为多次返回会使阅读变得更加困难并且更难以调试(当然在非常简单的情况下它并不适用)。我想这只是个人喜好,最后你可以使用任何一种方法来实现同样的事情

当某种特殊情况发生时,我倾向于使用多个回报。比如如果(有理由不继续)返回;

答4:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

这是 Java 语言规范中的官方用语。

14.20.2. Execution of try-finally and try-catch-finally

通过首先执行 try 块来执行带有 finally 块的 try 语句。然后有一个选择:如果 try 块的执行正常完成,[…] 如果 try 块的执行由于抛出值 V 而突然完成,[…] 如果 try 块的执行突然完成由于任何其他原因 R,然后执行 finally 块。然后有一个选择:如果 finally 块正常完成,那么 try 语句由于原因 R 突然完成。如果 finally 块由于原因 S 突然完成,那么 try 语句由于原因 S 突然完成(并且原因 R 被丢弃)。

return 的规范实际上明确说明了这一点:

JLS 14.17 The return Statement

ReturnStatement: return Expression(opt) ;没有 Expression 的 return 语句尝试将控制权转移给包含它的方法或构造函数的调用者。带有 Expression 的 return 语句试图将控制权转移给包含它的方法的调用者;表达式的值成为方法调用的值。前面的描述说的是“尝试转移控制”,而不仅仅是“转移控制”,因为如果方法或构造函数中有任何 try 语句,其 try 块包含 return 语句,那么这些 try 语句的任何 finally 子句都将被执行,在在将控制权转移到方法或构造函数的调用者之前,按从内到外的顺序。 finally 子句的突然完成可能会中断由 return 语句启动的控制转移。

答5:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

除了其他响应之外,重要的是要指出“终于”有权覆盖 try…catch 块的任何异常/返回值。例如,以下代码返回 12:

public static int getMonthsInYear() {

try {

return 10;

}

finally {

return 12;

}

}

同样,下面的方法也不会抛出异常:

public static int getMonthsInYear() {

try {

throw new RuntimeException();

}

finally {

return 12;

}

}

虽然以下方法确实抛出了它:

public static int getMonthsInYear() {

try {

return 12;

}

finally {

throw new RuntimeException();

}

}

应该注意的是,中间情况正是在 finally 块中包含 return 语句绝对可怕的原因(它可以隐藏任何 Throwable)。

谁不想要一个被压制的OutOfMemoryError? ;)

我对其进行了测试,它确实抑制了这样的错误(耶!)。当我编译它时它也会生成一个警告(耶!)。您可以通过定义一个返回变量然后在 finally 块之后使用 return retVal after 来解决它,尽管这当然假设您抑制了一些其他异常,因为否则代码将没有意义.

答6:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

我尝试了上面的例子,稍作修改-

public static void main(final String[] args) {

System.out.println(test());

}

public static int test() {

int i = 0;

try {

i = 2;

return i;

} finally {

i = 12;

System.out.println("finally trumps return.");

}

}

上面的代码输出:

终于胜过回归。 2

这是因为在执行 return i; 时,i 的值为 2。此后,执行 finally 块,其中 12 分配给 i,然后执行 System.out out。

执行 finally 块后,try 块返回 2,而不是返回 12,因为此 return 语句不再执行。

如果您将在 Eclipse 中调试此代码,那么您会感觉到在执行 finally 块的 System.out 之后再次执行 try 块的 return 语句。但这种情况并非如此。它只是返回值 2。

这个例子很棒,它添加了几十个最终相关线程中没有提到的东西。我认为几乎没有任何开发人员会知道这一点。

如果 i 不是一个原始对象,而是一个 Integer 对象怎么办。

我很难理解这个案子。 docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.17 说,“带有 Expression 的 return 语句试图将控制权转移给包含它的方法或 lambda 主体的调用者......如果 Expression 的评估正常完成,则产生一个值 V..”可以从这个语句中猜到 - 似乎 return 不会在评估值 V 后再次评估表达式,这就是为什么更改 i 不会影响返回值,纠正我。

但是我找不到任何关于这一点的证据,它在哪里提到 return 不会再次评估表达式。

@meexplorer 有点晚了,但在 JLS 14.20.2. Execution of try-finally and try-catch-finally 中有解释 - 措辞有点复杂,还必须阅读 14.17. The return Statement

答7:

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

这是Kevin’s answer的详细说明。重要的是要知道要返回的表达式是在 finally 之前计算的,即使它是在之后返回的。

public static void main(String[] args) {

System.out.println(Test.test());

}

public static int printX() {

System.out.println("X");

return 0;

}

public static int test() {

try {

return printX();

}

finally {

System.out.println("finally trumps return... sort of");

}

}

输出:

X

finally trumps return... sort of

0

重要的是要知道。

很高兴知道,也很有意义。似乎实际返回 return 的值是 finally 之后的内容。计算返回值(此处为 printX())仍然在它之前。

没有。上面的代码应将 System.out.println("finally trumps return... sort of"); 替换为 System.out.print("finally trumps return in try"); return 42;

这个答案在 IMO 中是完全不言而喻的,因为 return 不会返回一些只有在调用者打印它或其他什么时才会被评估的魔法延续。 printX() 在 return 发生之前被调用,无论任何 try/catch 或其他任何内容。

答8:

huntsbot.com – 高效赚钱,自由工作

这就是 finally 块的全部想法。它可以让你确保你做的清理工作可能会因为你返回而被跳过,当然,除其他外。

不管发生什么在 try 块中最终都会被调用(除非您调用 System.exit(int) 或 Java 虚拟机因其他原因退出)。

这是一个极其微弱的答案。 stackoverflow.com/a/65049/715269

答9:

huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

考虑这个问题的一个合乎逻辑的方法是:

放置在 finally 块中的代码必须在 try 块中发生的任何情况下执行因此,如果 try 块中的代码尝试返回值或抛出异常,则该项目将被放置在“架子上”直到 finally 块可以执行因为代码在finally 块(根据定义)具有高优先级,它可以返回或抛出任何它喜欢的东西。在这种情况下,任何留在“架子上”的东西都会被丢弃。唯一的例外是如果虚拟机在尝试块期间完全关闭,例如通过“System.exit”

这只是“一种合乎逻辑的思考方式”还是 finally 块实际上是如何根据规范工作的?一个指向 Sun 资源的链接在这里会非常有趣。

答10:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

finally 总是被执行,除非有异常的程序终止(比如调用 System.exit(0)…)。所以,你的系统输出将被打印出来

答11:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

不,并非总是一种例外情况是// System.exit(0);在 finally 块阻止 finally 被执行之前。

class A {

public static void main(String args[]){

DataInputStream cin = new DataInputStream(System.in);

try{

int i=Integer.parseInt(cin.readLine());

}catch(ArithmeticException e){

}catch(Exception e){

System.exit(0);//Program terminates before executing finally block

}finally{

System.out.println("Won't be executed");

System.out.println("No error");

}

}

}

这就是你真的不应该调用 System.exit() 的原因之一......

原文链接:https://www.huntsbot.com/qa/w7bo/does-a-finally-block-always-get-executed-in-java?lang=zh_CN&from=csdn

huntsbot.com – 高效赚钱,自由工作

好文阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: