【2021-07-12】当代码执行到 try 语句块时,finally 语句块一定会被执行么?

489 阅读1分钟

请移步至 【DobbyKim 的每日一题】 查看更多的题目~

答:

不一定

有两种情况会导致即便代码执行到 try 块,finally 块也有可能不执行:

  1. 系统终止
  2. 守护线程被终止

示例程序一:

package com.github.test;

public class Test {

    public static void main(String[] args) {
        foo();
    }

    public static void foo() {
        try {
            System.out.println("In try block...");
            System.exit(0);
        } finally {
            System.out.println("In finally block...");
        }
    }
}

该程序运行的结果为:

In try block...

原因在于,try 块中,我们使用了 System.exit(0) 方法,该方法会终止当前正在运行的虚拟机,也就是终止了系统,既然系统被终止,自然而然也就执行不到 finally 块的代码了。

示例程序二:

package com.github.test;

public class Test {

    public static void main(String[] args) {
        Thread thread = new Thread(new Task());
        thread.setDaemon(true);
        thread.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

class Task implements Runnable {

    @Override
    public void run() {
        try {
            System.out.println("In try block...");
            Thread.sleep(5000); // 阻塞线程 5 s
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("In finally block");
        }
    }
}

该程序的输出结果为:

In try block...

Java 的线程可以分为两大类:

  • Daemon Thread(守护线程)
  • User Thread(用户线程)

所谓的守护线程就是指程序运行的时候,再后台提供一种通用服务的线程,比如垃圾回收线程就是一个守护线程。守护线程并不属于程序中不可或缺的部分,因此,当所有的用户线程结束,程序也就终止,程序终止的同时回杀死进程中所有的守护线程。

上面的实力程序中,main 执行完毕,程序就终止了,所以守护线程也就被杀死,finally 块的代码也就无法执行到了。