考虑到这段代码,我能绝对确定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");
}
考虑到这段代码,我能绝对确定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");
}
当前回答
如果抛出异常,则最终运行。如果未引发异常,则最终运行。如果捕获到异常,则最终运行。如果未捕获异常,则最终运行。
只有当JVM退出时,它才不会运行。
其他回答
是的,会的。无论try或catch块中发生什么,除非调用System.exit()或JVM崩溃。如果块中有任何return语句,finally将在该return语句之前执行。
考虑这一点的逻辑方法是:
放置在finally块中的代码必须在try块中执行因此,如果try块中的代码试图返回一个值或抛出一个异常,则该项将被“搁置”,直到finally块可以执行因为finally块中的代码(根据定义)具有高优先级,所以它可以返回或抛出任何它喜欢的东西。在这种情况下,“搁在架子上”的任何东西都会被丢弃。唯一的例外是,如果VM在try块期间完全关闭,例如通过“System.exit”
我尝试了上面的示例,但稍作修改-
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.
这是因为当返回i;i的值为2。在此之后,执行finally块,其中12被分配给i,然后执行System.out-out。
在执行finally块之后,try块返回2,而不是返回12,因为该返回语句不会再次执行。
如果您将在Eclipse中调试此代码,那么您会感觉到在执行System.out of finally块之后,try块的返回语句将再次执行。但事实并非如此。它只返回值2。
不总是这样
Java语言规范描述了try-catch finally和try-catch块在14.20.2在任何地方,它都不会指定始终执行finally块。但对于try-catch-finally和try-finally块完成的所有情况,它确实指定在完成之前必须执行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不能保证finally块总是在try块之后执行?因为这是不可能的。在完成try块之后但在执行finally块之前,JVM不太可能被中止(终止、崩溃、断电)。JLS无法避免这种情况。
因此,任何软件的正常行为都取决于最终块,总是在其尝试块完成后执行。
try块中的返回指令与此问题无关。如果执行在try-catch finally之后到达代码,则可以保证finally块之前已经执行过,无论是否在try块内有返回指令。
除其他响应外,重要的是要指出,“finally”有权通过try重写任何异常/返回值。。捕捉块。例如,以下代码返回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();
}
}