是否finally块总是用Java执行?
考虑到这段代码,我能绝对确定无论something()
是finally
块始终执行吗?
try { something(); return success;
}
catch (Exception e) { return failure;
}
finally { System.out.println("I don't know if this will get printed out");
}
#1楼
除了最后要替换try块中的return的return以外,异常也是如此。 引发异常的finally块将替换try块中引发的return或异常。
#2楼
不,并非总是一种例外情况是// 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");}}
}
#3楼
是的,它会的。 不管您在try或catch块中发生了什么,除非调用System.exit()或JVM崩溃。 如果块中有任何return语句,最后将在该return语句之前执行。
#4楼
这是凯文答案的详细说明。 重要的是要知道要返回的表达式是在finally
之前求值的,即使它是在after之后返回的。
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
#5楼
是的,它会的。 唯一的情况是JVM退出或崩溃
#6楼
简而言之,在正式的Java文档(单击此处 )中,写道-
如果在执行try或catch代码时JVM退出,则finally块可能不会执行。 同样,如果执行try或catch代码的线程被中断或杀死,即使整个应用程序继续运行,finally块也可能不会执行。
#7楼
是的,finally块始终执行。 大多数开发人员使用此块来关闭数据库连接,结果集对象,语句对象,并且还使用到Java休眠中来回滚事务。
#8楼
finally
将执行,这是肯定的。
在以下情况下, finally
将不会执行:
情况1 :
当您执行System.exit()
。
情况2:
当您的JVM /线程崩溃时。
情况3:
在手动之间停止执行时。
#9楼
总而言之,总是运行finally,仅仅是因为它在返回之后出现在代码中并不意味着它就是这样实现的。 退出try
块时,Java运行时负责运行此代码。
例如,如果您具有以下条件:
int foo() { try {return 42;}finally {System.out.println("done");}
}
运行时将生成如下内容:
int foo() {int ret = 42;System.out.println("done");return 42;
}
如果抛出未捕获的异常,则将运行finally
块,并且该异常将继续传播。
#10楼
因为除非您调用System.exit()
(否则线程崩溃),否则将始终调用finally块。
#11楼
那就是finally块的整个想法。 它可以确保您进行清理,否则您可能会跳过清理,因为您除其他外当然会返回。
无论 try块中发生了什么, Finally都会被调用( 除非您调用System.exit(int)
或Java虚拟机由于其他原因而退出)。
#12楼
除了其他响应之外,重要的一点是要指出,“最终”有权通过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();}
}
#13楼
这是因为您将i的值分配为12,但没有将i的值返回给函数。 正确的代码如下:
public static int test() {int i = 0;try {return i;} finally {i = 12;System.out.println("finally trumps return.");return i;}
}
#14楼
这是Java语言规范中的正式用语。
14.20.2。 最终尝试和最终捕获的执行
通过首先执行
try
块来执行带有finally
块的try
语句。 然后有一个选择:
- 如果
try
块的执行正常完成,则[...]- 如果由于
throw
值V导致try
块的执行突然完成,[...]- 如果
try
块的执行由于任何其他原因R突然完成,则将执行finally
块。 然后有一个选择:
- 如果finally块正常完成,则
try
语句由于原因R突然完成。- 如果
finally
块由于S突然完成,则try
语句由于S突然完成( 并且R被丢弃 )。
实际上, return
的说明使这一点很明确:
JLS 14.17返回声明
ReturnStatement: return Expression(opt) ;
没有
Expression
return
语句尝试将控制权转移到包含该方法的方法或构造函数的调用者。一个带有
Expression
return
语句试图将控制权转移到包含它的方法的调用者。Expression
的值成为方法调用的值。前面的描述说的是“ 尝试转移控制权 ”,而不仅仅是“ 转移控制权 ”,因为如果方法或构造函数中有任何
try
语句的try
块包含return
语句,则这些try
语句的所有finally
子句都将被执行,在控制权转移到方法或构造函数的调用者之前,从最里面到最外面的顺序。finally
子句的突然完成会破坏由return
语句启动的控制权的转移。
#15楼
我尝试对上面的示例进行了一些修改-
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中调试此代码,那么您会感到在执行System.out
of finally
块之后, try
块的return
语句将再次执行。 但这种情况并非如此。 它只是返回值2。
#16楼
不总是
Java语言规范描述了try-catch-finally和try-catch块在14.20.2的工作方式
它在任何地方都没有指定始终执行finally块。 但是对于try-catch-finally和try-finally块完成的所有情况,它都指定必须在完成之前最终执行。
try {CODE inside the try block
}
finally {FIN code inside finally block
}
NEXT code executed after the try-finally block (may be in a different method).
JLS不保证在CODE之后执行FIN 。 JLS保证,如果执行CODE和NEXT ,则FIN将始终在CODE之后和NEXT之前执行。
JLS为什么不保证在try块之后总是执行finally块? 因为这是不可能的。 在完成try块之后但在执行finally块之前,JVM不太可能会中止(终止,崩溃,关闭电源)。 JLS无法采取任何措施来避免这种情况。
因此,任何由于其正常行为而取决于try块完成后始终执行的finally块的软件都会受到错误攻击。
try块中的返回与该问题无关。 如果在try-catch-finally之后执行到达代码,则可以确保finally块将在try块内有或没有返回之前被执行。
#17楼
答案很简单YES。
输入:
try{int divideByZeroException = 5 / 0;
} catch (Exception e){System.out.println("catch");return; // also tried with break; in switch-case, got same output
} finally {System.out.println("finally");
}
输出:
catch
finally
#18楼
- 最后,Block总是被执行。 除非并且直到System.exit()语句存在(finally块中的第一个语句)。
- 如果system.exit()是first语句,则不会执行finally块,并且控制会从finally块中取出。 每当System.exit()语句进入finally块,直到该语句finally块被执行,并且当System.exit()出现时,控制力就会完全从finally块中消失。
#19楼
如果不处理异常,则在终止程序之前,JVM将执行finally块。 仅由于以下这些原因,仅当程序的正常执行失败而导致程序终止时,它才会执行。
通过引起致命错误,导致流程中止。
由于内存损坏导致程序终止。
通过调用System.exit()
如果程序进入无限循环。
#20楼
是的,因为没有控制语句可以阻止finally
执行。
这是一个参考示例,其中将执行所有代码块:
| x | Current result | Code
|---|----------------|------ - - -
| | |
| | | public static int finallyTest() {
| 3 | | int x = 3;
| | | try {
| | | try {
| 4 | | x++;
| 4 | return 4 | return x;
| | | } finally {
| 3 | | x--;
| 3 | throw | throw new RuntimeException("Ahh!");
| | | }
| | | } catch (RuntimeException e) {
| 4 | return 4 | return ++x;
| | | } finally {
| 3 | | x--;
| | | }
| | | }
| | |
|---|----------------|------ - - -
| | Result: 4 |
在下面的变体中, return x;
将被跳过。 结果仍然是4
:
public static int finallyTest() {int x = 3;try {try {x++;if (true) throw new RuntimeException("Ahh!");return x; // skipped} finally {x--;}} catch (RuntimeException e) {return ++x;} finally {x--;}
}
当然,参考资料会追踪他们的状态。 此示例返回value = 4
的引用:
static class IntRef { public int value; }
public static IntRef finallyTest() {IntRef x = new IntRef();x.value = 3;try {return x;} finally {x.value++; // will be tracked even after return}
}
#21楼
除了其他答案外,添加到@vibhash的答案还可以说明在可变对象(如以下对象)的情况下会发生什么。
public static void main(String[] args) {System.out.println(test().toString());
}public static StringBuffer test() {StringBuffer s = new StringBuffer();try {s.append("sb");return s;} finally {s.append("updated ");}
}
将输出
sbupdated
#22楼
考虑以下程序:
public class SomeTest {private static StringBuilder sb = new StringBuilder();public static void main(String args[]) {System.out.println(someString());System.out.println("---AGAIN---");System.out.println(someString());System.out.println("---PRINT THE RESULT---");System.out.println(sb.toString());}private static String someString() {try {sb.append("-abc-");return sb.toString();} finally {sb.append("xyz");}}
}
从Java 1.8.162开始,以上代码块提供以下输出:
-abc-
---AGAIN---
-abc-xyz-abc-
---PRINT THE RESULT---
-abc-xyz-abc-xyz
这意味着使用finally
释放对象是一个好习惯,例如以下代码:
private static String someString() {StringBuilder sb = new StringBuilder();try {sb.append("abc");return sb.toString();} finally {sb = null; // Just an example, but you can close streams or DB connections this way.}
}
#23楼
是的,在try
或catch
代码块执行之后, finally
将被调用。
finally
不会被调用的唯一时间是:
- 如果您调用
System.exit()
- 如果调用
Runtime.getRuntime().halt(exitStatus)
- 如果JVM首先崩溃
- 如果JVM在
try
或catch
块中达到了无限循环(或其他不间断,不终止的语句) - 操作系统是否强行终止了JVM进程; 例如,在UNIX上
kill -9 <pid>
- 如果主机系统死机; 例如,电源故障,硬件错误,操作系统崩溃等
- 如果
finally
块将由守护程序线程执行,并且所有其他非守护程序线程退出,则在调用finally
之前
#24楼
除非有异常的程序终止(例如调用System.exit(0)..),否则总是执行finally。 因此,您的sysout将被打印
#25楼
是的,它将被调用。 这就是拥有finally关键字的全部意义。 如果跳出try / catch块可以跳过finally块,则与将System.out.println放在try / catch外部相同。
#26楼
示例代码:
public static void main(String[] args) {System.out.println(Test.test());
}public static int test() {try {return 0;}finally {System.out.println("finally trumps return.");}
}
输出:
finally trumps return.
0
#27楼
实际上,在任何语言中都是如此……最终总是在return语句之前执行,无论该return在方法主体中的何处。 如果不是这种情况,那么finally块将没有太大的意义。
#28楼
除非由于JVM崩溃或对System.exit(0)
的调用而导致程序异常终止,否则总是执行finally块。
最重要的是,从finally块内返回的任何值都将覆盖执行finally块之前返回的值,因此在使用try finally时请务必检查所有退出点。
#29楼
另外,尽管这是不好的做法,但是如果finally块中有return语句,它将胜过常规块中的其他任何返回。 也就是说,以下块将返回false:
try { return true; } finally { return false; }
从finally块中抛出异常也是一样。
#30楼
最后返回也将丢弃任何异常。 http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
#31楼
考虑这一点的逻辑方法是:
- 无论 try块内发生什么,都必须执行放置在finally块中的代码
- 因此,如果try块中的代码尝试返回值或引发异常,则将该项目“放在架子上”,直到finally块可以执行为止
- 因为finally块中的代码(根据定义)具有较高的优先级,所以它可以返回或抛出任何喜欢的东西。 在这种情况下,“架子上”剩下的任何东西都将被丢弃。
- 唯一的例外是VM是否在try块中完全关闭,例如通过“ System.exit”关闭
是否finally块总是用Java执行?相关推荐
- javascript rsa java,用javascript与java执行
RSA加密与解密
用javascript与java执行 RSA加密与解密 2009-12-12 14:58:30 出处:https://www.yqdown.com 这几天一直做安全登录,网上查了好多资料,不尽如意 ...
- java执行exe 没捕获到输出_Java程序员注意——六种异常处理的陋习
你觉得自己是一个Java专家吗?是否肯定自己已经全面掌握了Java的异常处理机制?在下面这段代码中,你能够迅速找出异常处理的六个问题吗? OutputStreamWriter out = ... ja ...
- java 静态代码块_关于Java你不知道的那些事之代码块
前言 普通代码块:在方法或语句中出现的{},就被称为代码块 静态代码块:静态代码块有且仅加载一次,也就是在这个类被加载至内存的时候 普通代码块和一般语句执行顺序由他们在代码中出现的次序决定,先出现先执 ...
- java里的初始化块_[转载] Java 语言中的实例初始化块 ( IIB) 详解
参考链接: Java中的实例初始化块(IIB) 在 Java 语言中的类初始化块 文章中我们简单的介绍了下 Java 中的实例初始化块 ( IIB ).不过我觉得介绍的有点简单了,于是,再写一篇文章详 ...
- Java入门-Java执行语句
Java入门--Java执行语句 1.顺序语句 顺序语句:方法里的代码从上往下执行 2.分支语句if 和 switch 分支语句:根据某个条件执行不同的功能 2.1 if 1.简单if分支语句 ...
- 代码块:在Java中,使用{}括起来的代码被称为代码块。
/*代码块:在Java中,使用{}括起来的代码被称为代码块.根据其位置和声明的不同,可以分为局部代码块:局部位置,用于限定变量的生命周期.构造代码块:在类中的成员位置,用{}括起来的代码.每次调用构造 ...
- java执行反射代码导致频繁创建奇怪的类从而发生元数据区被占满FUllGc案例
查看 JVM GC 日志 没有一丝耽搁,老王立刻调出了线上GC日志,在日志里,看到了一个"Metadata GC Threshold"的字样,类似于如下日志: [Full GC(M ...
- 代码块:在Java中用{}括起来的代码
代码块:在Java中用{}括起来的代码 (1)在Java中用{}括起来的代码. (2)代码块分类:(根据其位置和声明的不同) A:局部代码块 在方法定义中,用于限定变量的生命周期,及早释放,提高内存利 ...
- java -version cmd_java如何运行步骤cmd?Java执行cmd命令方法有哪些?
写好一个java程序之后,我们的最终目的就是可以正确的运行程序,如果程序运行正确了,那么代码也就没有什么问题了,可是java如何运行步骤cmd?接下来,我们就来给大家讲解一下这方面的内容. 1.首先用 ...
最新文章
- 在GitHub上搭建GitHub Pages博客-- Jekyll
- c++函数内部可以返回函数内部定义的指针 但是不能返回函数内部定义的数组...
- LeetCode Reverse Nodes in k-Group(单链表连续分段反转)
- Laravel 实现定时任务
- 1 张图秒懂 Nova 16 种操作 - 每天5分钟玩转 OpenStack(44)
- jax-rs jax-ws_什么是JAX-RS注释? (第3部分)
- 请不要做浮躁的嵌入式系统工程师(谨以此文与大家共勉)
- UVA10838 The Pawn Chess
- 阿里云为什么在十三年后重构调度系统?
- 使用ColorUI组件
- 解决网易云音乐登录接口-460问题
- 全国各省电信及网通DNS大全
- java对打字速度,java课程设计-- 打字速度测试程序
- Pwn level题目
- 为什么文本框里的字只显示一半_Word文本框文字显示不全、无法选择、不能编辑调整大小和跨页,怎么解决...
- 《 指数基金投资指南 》by 银行螺丝钉 - 笔记 - 4 - 第二部分
- python实现地理位置类数据爬取与geohash应用初探
- python定义变量类型为数字_python 学习(四)- 变量类型
- LeetCode 974. 和可被 K 整除的子数组 | Python
- CTF比赛中常见的MISC解题方法(不涉及内存取证和流量分析)仅供菜鸟,大佬绕道
热门文章
- 解决Please ensure that adb is correctly located at 'D:\java\sdk\platform-tools\adb.exe' and can be exe
- php 将内容中的图片的域名,php给编辑器中的图片地址添加域名
- python从文件中读取数据_使用Python脚本从文件读取数据代码实例
- Android之如何卸载指定的 应用程序
- 简单图片浏览器的实现
- Flutter开发之数据存储-1-SharedPreferences(32)
- dataframe 查找特定值_省时省力的查找引用函数
- 领结婚证了,新的人生开始了!
- MySQL学习随笔记录
- 每瓶啤酒2元,2个空酒瓶或4个瓶盖可换1瓶啤酒。10元最多可喝多少瓶啤酒?