zoukankan      html  css  js  c++  java
  • finally代码块不被执行的情况总结

    以前跟别人讨论finally关键字,我总是简单的说:“fianly代码块中的代码一定会执行,一般用来清除IO资源等非内存资源(内存资源由GC机制回收)”。 今天翻书发现了几种不会执行的情况,现在总结下。

    1.finally的含义

    finally的真正含义是指从try代码块出来才一定会执行相应的finally代码块。

    public class Test {
        public static void main(String[] args) {
            foo(false);
        }
        public static void foo(boolean flag) {
            System.out.println("enter foo()");
            if(flag) {
              try {
                  System.out.println("enter try block");
              } finally {
                  System.out.println("enter finally block");
              }
            } else {
                System.out.println("leave foo()");
            }
    
        }
    }
    /******************
    控制台打印如下
    enter foo()
    leave foo()
    *******************/

    上述代码,flag为false,没有进入try代码块,对应的finally自然也不会执行。

    2.System.exit()

    System.exit()的作用是中止当前虚拟机,虚拟机都被中止了,finally代码块自然不会执行。

    public class Test {
        public static void main(String[] args) {
            foo();
        }
        public static void foo() {
            System.out.println("enter foo()");
           try {
                System.out.println("enter try block");
                System.exit();
           } finally {
                System.out.println("enter finally block");
           }
        }
    }
    /*****************
    控制台打印如下
    enter foo()
    enter try block
    ******************/

    上述代码,进入foo()方法后再进入try代码块,但是在进入finally代码块之前调用了System.exit()中止虚拟机, finally代码块不会被执行。

    3.守护(daemon)线程被中止时

    java线程分为两类,守护线程和非守护线程。当所有的非守护线程中止时,不论存不存在守护线程,虚拟机都会kill掉守护线程从而中止程序。 虚拟机中,执行main方法的线程就是一个非守护线程,垃圾回收则是另一个守护线程,main执行完,程序就中止了,而不管垃圾回收线程是否中止。 所以,如果守护线程中存在finally代码块,那么当所有的非守护线程中止时,守护线程被kill掉,其finally代码块是不会执行的。

    public class Test {
        public static void main(String[] args) {
            Thread t = new Thread(new Task());
            t.setDaemon(true); //置为守护线程
            t.start();
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                throw new RuntimeException("the "+Thread.currentThread().getName()+" has been interrupted",e);
            }
        }
    }
    class Task implements Runnable {
        @Override
        public void run() {
             System.out.println("enter run()");
            try {
                System.out.println("enter try block");
                TimeUnit.SECONDS.sleep(5); //阻塞5s
            } catch(InterruptedException e) {
                System.out.println("enter catch block");
                throw new RuntimeException("the "+Thread.currentThread().getName()+" has been interrupted",e);
            } finally {
                System.out.println("enter finally block");
            }      
        }
    }
    /*******************
    控制台打印如下
    enter run()
    enter try block
    ********************/

    上述代码,main()执行完,非守护线程也就结束了,虽然线程t处于阻塞状态,但由于其是守护线程,所以程序仍会中止。 而且,即使其进入了try代码块,finally代码块也不会被执行。

    总结

    finally代码块并非一定执行,在不进入try代码块或者程序被中止时就不会执行。

    引用

    1.《Java编程思想》

  • 相关阅读:
    1、使用Xcode修改iOS项目工程名和路径名
    ios 里如何处理四舍五入的问题
    ios app 开发中ipa重新签名步骤介绍
    如何重新签名ipa文件
    最近研究xcodebuild批量打包的一些心得
    C#Timer
    插座断电提醒(测试阶段)
    C#MessageBox 自动关闭窗口
    插座继电器测试
    C# TCPListener
  • 原文地址:https://www.cnblogs.com/fudashi/p/6498205.html
Copyright © 2011-2022 走看看