有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么finally块中的语句仍在执行?

public class ADaemon implements Runnable {
@Override
public void run() {
    try {
        System.out.println("Starting ADaemon");
        TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
        System.out.println("Exiting via InterruptedException");
    } finally {
        System.out.println("This should always run?");
    }
}

public static void main(String... args) {
    Thread t = new Thread(new ADaemon());
    t.setDaemon(true);
    t.start();
}}

结果

Starting ADaemon
Exiting via InterruptedException
This should always run?

我试图从《Java思考》第四版中获取代码示例,但没有得到书中描述的结果,finally块仍在执行,为什么会这样?顺便说一句,我使用的是oracle jdk 10.0.1

------更新----------

我的maven runner插件似乎运行了一些东西,我禁用了它,结果与书中描述的一样


共 (2) 个答案

  1. # 1 楼答案

    finally block是一个强大的工具(如果使用不当,它会很危险),它几乎总是在try or catch block完成后运行(尽管上面突出显示了一些小情况)。 看看这个例子:

    try{
      throw new Exception();
    }catch(Exception e){
    return;
    }finally{
    System.out.println("Shouldn't run?");
    }
    

    如果这是在一个方法中,那么finally块仍将被执行(千万不要这样做,因为这是一个糟糕的做法)。它被设计为执行任何清理,不管您所做的操作的结果如何,比如关闭流(现在可以通过语句“try”中的parantise自动完成)

  2. # 2 楼答案

    你说书上说:

    "the finally block may not be executed".

    (重点补充。)

    这与说:

    "the finally block will not be executed".

    我认为这本书的意思是,当应用程序退出时,守护进程线程是否会得到中断(或其他什么),这是未指明的(可能是JVM特定的)

    当然,如果守护进程线程捕获并忽略了如下所示的“中断”异常,那么我将期望永远不会执行finally

    public class ADaemon implements Runnable {
        @Override
        public void run() {
            try {
                System.out.println("Starting ADaemon");
                while (true) {
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        System.out.println("Caught InterruptedException");
                    }
                }
            } finally {
                System.out.println("This should always run?");
            }
        }
    
        public static void main(String... args) {
            Thread t = new Thread(new ADaemon());
            t.setDaemon(true);
            t.start();
        }
    }
    

    如果守护进程线程没有执行可中断的代码,我会预期类似的行为