考虑到这段代码,我能绝对确定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");
}
当前回答
我对不同论坛上提供的所有答案感到非常困惑,最终决定编码并查看。输出为:
即使try-and-catch块中有返回,也将执行finally。
try {
System.out.println("try");
return;
//int i =5/0;
//System.exit(0 ) ;
} catch (Exception e) {
System.out.println("catch");
return;
//int i =5/0;
//System.exit(0 ) ;
} finally {
System.out.println("Print me FINALLY");
}
输出
尝试最后打印我
如果返回被上述代码中try-and-catch块中的System.exit(0)替换,并且由于任何原因,在它之前发生了异常。
其他回答
尝试这段代码,您将了解finally块中的代码是在return语句之后执行的。
public class TestTryCatchFinally {
static int x = 0;
public static void main(String[] args){
System.out.println(f1() );
System.out.println(f2() );
}
public static int f1(){
try{
x = 1;
return x;
}finally{
x = 2;
}
}
public static int f2(){
return x;
}
}
我对不同论坛上提供的所有答案感到非常困惑,最终决定编码并查看。输出为:
即使try-and-catch块中有返回,也将执行finally。
try {
System.out.println("try");
return;
//int i =5/0;
//System.exit(0 ) ;
} catch (Exception e) {
System.out.println("catch");
return;
//int i =5/0;
//System.exit(0 ) ;
} finally {
System.out.println("Print me FINALLY");
}
输出
尝试最后打印我
如果返回被上述代码中try-and-catch块中的System.exit(0)替换,并且由于任何原因,在它之前发生了异常。
是的,finally将在执行try或catch代码块后调用。
唯一不会被调用的时间是:
如果调用System.exit()如果调用Runtime.getRuntime().hart(exitStatus)如果JVM首先崩溃如果JVM到达try或catch块中的无限循环(或其他一些不可中断、不终止的语句)如果操作系统强制终止JVM进程;例如,在UNIX上,kill-9<pid>如果主机系统失效;例如,电源故障、硬件错误、操作系统死机等如果finally块将由守护程序线程执行,并且所有其他非守护程序线程在finally调用之前退出
以下是一些可以绕过finally块的条件:
如果在执行try或catch代码时JVM退出,那么finally块可能不会执行。更多太阳教程正常关闭-当最后一个非守护程序线程退出时,或者当Runtime.exit()(一些不错的博客)时,都会发生这种情况。当线程退出时,JVM会对正在运行的线程进行盘点,如果只剩下守护进程线程,则会启动有序关闭。当JVM停止时,所有剩余的守护程序线程都将被放弃。如果不执行块,堆栈也不会被解开,JVM只会退出。守护程序线程应该很少使用,很少有处理活动可以在任何时候安全地放弃,而无需清理。特别是,将守护程序线程用于可能执行任何类型I/O的任务是危险的。守护程序线程最好保存用于“内务管理”任务,例如后台线程,它定期从内存缓存中删除过期条目(源)
最后一个非守护程序线程退出示例:
public class TestDaemon {
private static Runnable runnable = new Runnable() {
@Override
public void run() {
try {
while (true) {
System.out.println("Is alive");
Thread.sleep(10);
// throw new RuntimeException();
}
} catch (Throwable t) {
t.printStackTrace();
} finally {
System.out.println("This will never be executed.");
}
}
};
public static void main(String[] args) throws InterruptedException {
Thread daemon = new Thread(runnable);
daemon.setDaemon(true);
daemon.start();
Thread.sleep(100);
// daemon.stop();
System.out.println("Last non-daemon thread exits.");
}
}
输出:
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Last non-daemon thread exits.
Is alive
Is alive
Is alive
Is alive
Is alive
是的,因为没有控制语句可以阻止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 |
在下面的变体中,返回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--;
}
}
当然,引用可以跟踪其状态。此示例返回值为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
}
}