finally 的作用
finally 是 Java 异常处理机制的组成部分,它保证了代码块中的代码一定要被执行。通常我们会将资源释放的代码写在 finally 代码块中,如 I/O 的关闭、数据库连接的关闭等。
但是也会存在 finally 代码块中的代码不会执行的情况,本文就是总结了这些情况。
finally 代码块不会执行的情况
之前在网上的帖子看到有一种情况是叫做”不进入 try 代码块“,这不废话吗,不进入 try 当然不会执行 finally 代码块。所以本文讨论的是进入 try 代码块后 finally 代码块不执行的情况。
1. 虚拟机被终止 System.exit();
System.exit(0)
的作用是中止当前正在运行的 Java 虚拟机。如果虚拟机被中止,程序也会被终止,所以在它后面的代码都不会被执行,即便是 finally 代码块也同样不会执行。
private static void demo1() {
try {
System.out.println("执行 try 代码块");
System.exit(0);
} finally {
System.out.println("开始执行 finally 代码块");
}
}
/**控制台输出:
执行 try 代码块
**/
2. try 代码块无限循环
这是由于业务逻辑的原因,一直在执行 try 代码块的业务并且永远无法终止,try 代码块都没执行完,自然无法执行 finally 代码块。
private static void demo2() {
try {
while (true) {
// do something
System.out.println("执行 try 代码块");
}
} finally {
System.out.println("开始执行 finally 代码块");
}
}
/**控制台输出:
执行 try 代码块
执行 try 代码块
...(一直输出)
**/
3. 在被中止的守护线程内
Java 中的线程可以分为守护线程和用户线程。当程序中所有的用户线程都终止时,虚拟机会 kill 所有的守护线程来终止程序。
当 try-finally 代码块存在于守护线程,而此守护线程因用户线程被销毁而终止时,该守护线程不会继续执行。
假设用户线程(main线程)执行完毕后,作为守护线程的 thread 对象中的 try 代码块还没有执行结束,当用户线程执行结束后,此时已不存在用户线程,虚拟机会强制中止守护线程 thread,导致 finally 代码块不会被执行。
private static void demo3() {
Thread thread = new Thread(() -> {
try {
System.out.println("执行 try 代码块,等待2s,等待主线程执行结束...");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("开始执行 finally 代码块");
}
});
thread.setDaemon(true);
thread.start();
}
/**控制台输出:
执行 try 代码块,等待2s,等待主线程执行结束...
**/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。