1. 程式人生 > 其它 >看了你就掌握---------JAVA中finally語句塊的詳解!!!!!

看了你就掌握---------JAVA中finally語句塊的詳解!!!!!

技術標籤:javajvm程式語言

關於JAVA中finally語句塊的詳解

目錄

前言

相信同學們學習到面向物件的異常處理中應該會踩到finally語句塊這個坑中,本篇博文通過各種案例幫你如何避免踩坑,踩雷,讓你對異常處理的學習更加透徹,finally語句塊掌握的更加紮實!


一、finally語句塊的特點及應用場景

在進行異常處理時,finally語句塊也在異常的處理格式中,finally語句塊是整個異常處理的統一出口,不管是產生了異常還是未產生異常,那麼finally語句塊中的內容必然執行。

來一個小案例:

import java.lang.Exception;
public class Exception1 {
    public static void main(String[] args){
        int i = 10;
        int j = 0;
        try{
            System.out.println("輸入的結果為" + i/j);
        }catch (Exception e ){
            System.out.println("動動你的腦筋,除數不能為0"
); return; }finally { System.out.println("finally語句執行了!"); } } } 執行結果: 動動你的腦筋,除數不能為0 finally語句執行了!

看完這段程式碼有人就有疑惑,為什麼我在catch語句塊中return了為什麼後面的程式碼還會執行?

​ 因為我們在進行異常處理流程時,當catch語句塊執行到return的時候,我們需要做準備return的操作,雖然這個返回值沒有,但預設還是要把這個沒有返回值的東西返回(可能有點繞,慢慢理解),在這個準備的過程中,我們就把finally語句塊的內容執行了,執行完畢後,再return 結束掉這個方法。

二、finally語句塊在任何情況一定會執行嗎?

答案是:否!

第一種情況:JVM退出,finally不會執行。

import java.lang.Exception;
public class Exception2 {
    public static void main(String[] args){
        int i = 10;
        int j = 0;
        try{
            System.out.println("輸入的結果為" + i/j);
        }catch (Exception e ){
            System.out.println("動動你的腦筋,除數不能為0")
            System.exit(1);// 退出JVM
        }finally {
            System.out.println("finally語句執行了!");
        }
    }
執行結果:
    動動你的腦筋,除數不能為0

​ 這種情況下,我們發現finally語句塊並沒有執行。因為我們在catch語句塊中首先顯示了錯誤資訊,並退出了JAVA虛擬機器,導致程式碼執行到此處,整個程式就結束了。

第二種情況:異常處理前結束方法,finally不會執行。

​ 這種情況是在進行異常處理前就return,結束了方法,那麼後面的所有程式碼都不會執行,finally語句塊也一定不會執行(編譯器也不會讓你寫return之後的程式碼)。

第三種情況:在異常處理前,產生了其他的異常,finally不會執行。

public class Exception3 {
    public static void main(String[] args){
        int i = 10;
        int j = 0;
        System.out.println(i/j);
        try{
            System.out.println("try..........");
        }finally {
            System.out.println("finally.........");
        }
    }
}
執行結果:
	Exception in thread "main" java.lang.ArithmeticException: / by zero
		at kkb.Exception3.main(Exception3.java:6)

​ 這種情況是在處理異常前,產生了其他的異常,既出現異常,後面的程式碼不會執行,直接結束了方法。

三、finally和final的區別

​ 有很多同學不知道finally和final是幹什麼的,就像方法的過載和重寫一樣,都是名字差不多,但是它們的應用的場景完全不同,完全沒有共同點。

​ finally:finally是一個語句塊,是屬於異常處理結構的成員之一,無論異常是否發生,finally語句塊的內容一定輸出,所以當我們需要編寫無論發生什麼都必須執行的程式碼時,就可以在finally語句塊中。

​ final:final是一個關鍵字,可以修飾類、變數和方法,被final修飾的類不可以被派生出新的子類。被final修飾的方法不能被重寫,不能修改方法中的內容。被fianl修飾的變數只能賦一次值,通常用fianl來修飾常量:public abstract final int +變數名。

四、finally常見踩坑面試題目

​ finally主要分為以下兩種題型,掌握了思想,那麼所有題目迎刃而解。

第一個案例:

class Person{	//建立一個Person類
    int age;	//屬性有age
}
public class Exception4 {
    public static void main(String[] args){
        Person p = p(); //呼叫p方法
        System.out.println(p.age); //輸入age的值
    }
    public static Person p(){
        Person p = new Person(); //建立Person物件
        p.age = 0;	//將預設值設為0
        try{
            p.age = 18;
            return p;
        }catch (Exception e){
            p.age = 10;
            return p;
        }finally {
            p.age = 20;
        }
    }
}
執行結果:
	20

題解:

​ 首先先分析流程 我們在try語句塊中將p.age設定為了18,然後返回這個物件,因為我們沒有設定年齡的限制,所以catch語句塊的內容一定不會執行。

​ 當代碼執行進入try語句塊時,首先將p.age設定為18,然後進入return p語句,在執行這段程式碼時,我們可以理解為先複製了這個p的記憶體地址,然後進入finally語句塊中,將p.age設定為了20,然後再將這個p儲存的記憶體地址返回。因為在堆物件中,這個p.age被finally語句塊改變,所以在返回的p中包含的已被修改後的p.age的值。所以最終列印的結果為20;

重點:當返回的資料時引用資料型別時,返回的是該物件的記憶體地址!!!

第二個案例:

public class Exception5 {
    public static void main(String[] args){
        int code = i();
        System.out.println(code);
    }
    public static int i(){
        int i = 0;
        try{
            return i;
        }finally {
            i = 20;
        }
    }
}
執行結果:
	0

題解:

​ 首先分析流程,在i()方法中我們先定義了個基本資料型別的變數i =0,在try語句塊中返回了這個i,在finally語句塊中修改了i的值。大家可能會認為,在try語句的return返回之前應該先執行finally語句塊,修改完畢後再返回嗎。最後輸出結果應該是20才對。

​ 流程:我們在return語句返回這個i之前,首先先把i的值(資料0)複製一份,然後進入finally語句塊,我們把i修改為20,然後再執行return,那麼return返回的仍然是這個複製好的資料。所以輸出是0;

總結兩道案例:

​ 這兩道案例一個返回的基本資料型別,一個是返回的引用資料型別。

區別:

​ 引用資料型別儲存的資料在堆中,執行完finally語句後,返回的是這個物件的記憶體地址複製,記憶體地址再指向物件,如果物件中的資料被改變,那麼記憶體地址指向的這個物件也會發生改變。

​ 區域性變數中基本資料型別的資料儲存在棧中,執行完finally語句後,返回的是這個資料本身的複製,如果資料被改變,那麼返回內容則不變。

總結

以上就是今天要講的內容,本文講解了finally語句塊的執行流程,通過一個個案例來告訴同學們在各種場景下的finally語句塊該如何執行的問題,希望能幫助到在此知識點上模糊的同學。
覺得有幫助的同學來個三連哦!