finally會不執行嗎???

不知道大家有沒有問過自己,finally方法會在什麼時候不執行呢???有些人可能會一臉懵逼的說:怎麼可能會不執行呢,那我們下面來看看finally到底會不會不執行。

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代碼塊或者程序被中止時就不會執行。所以寫代碼一定不要想當然,可能你認爲絕對不會執行的代碼,有時候它還真會執行,什麼時候我們都要帶着批判思維(熟話說:帶腦子)進行程序的開發。

想要更多幹貨、技術猛料的孩子,快點拿起手機掃碼關注我,我在這裏等你哦~

林老師帶你學編程https://wolzq.com

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章