【Java】final、finally、finalize
final、finally與finalize的區別
- final:final是一個修飾符,可以修飾類,方法和變數。final修飾類表示類不能被其它類繼承,並且該類中的所有方法都會隱式的被final修飾。final修飾方法,則該方法不能被重寫,若父類中final方法的訪問許可權為private,將導致子類中不能直接繼承該方法,因此,此時可以在子類中定義相同方法名的函式,此時不會與重寫final的矛盾,而是在子類中重新地定義了新方法。當final修飾一個基本資料型別時,表示該基本資料型別的值一旦在初始化後便不能發生變化;如果final修飾一個引用型別時,則在對其初始化之後便不能再讓其指向其他物件了,但該引用所指向的物件的內容是可以發生變化的。本質上是一回事,因為引用的值是一個地址,final要求值,即地址的值不發生變化。
- finally:finally作為異常處理的一部分,它只能用在try/catch語句中,並且附帶一個語句塊,表示這段語句最終一定會被執行(不管有沒有丟擲異常),經常被用在需要釋放資源的情況下。但須注意,在某些特殊情況下,finally塊是不會執行的。
- finalize:finalize()是Object中定義的一個方法,也就是每個物件都有這個方法。當垃圾回收器確定不存在對該物件的更多引用時(是個垃圾),由物件的垃圾回收器呼叫此方法。子類重寫
finalize
方法,以配置系統資源或執行其他清除,例如:一個socket連結,在物件初始化時建立,整個生命週期內有效,那麼就需要實現finalize,關閉這個連結。
try-catch-finally中try塊中有return,finally還會執行嗎?
會執行,當我們執行到return之後,我們不會立即返回,而是會接著執行finally塊裡面的程式碼,只有執行完,才會繼續執行我們的return值。
1、不管有沒有異常,finally中的程式碼都會執行
2、當try、catch中有return時,finally中的程式碼依然會繼續執行
3、finally是在return後面的表示式運算之後執行的,此時並沒有返回運算之後的值,而是把值儲存起來,不管finally對該值做任何的改變,返回的值都不會改變,依然返回儲存起來的值。也就是說方法的返回值是在finally運算之前就確定了的。
4、如果return的資料是引用資料型別,而在finally中對該引用資料型別的屬性值的改變起作用,try中的return語句返回的就是在finally中改變後的該屬性的值。
5、finally程式碼中最好不要包含return,程式會提前退出,也就是說返回的值不是try或catch中的值。
哪些特殊情況下,finally塊不會執行?
除非在try塊或者catch塊中呼叫了退出虛擬機器的方法(即System.exit(1);),否則不管在try塊、catch塊中執行怎樣的程式碼,出現怎樣的情況,異常處理的finally塊總是會被執行的。
不過,一般情況下,不要再finally塊中使用return或throw等導致方法終止的語句,因為一旦使用,將會導致try塊、catch塊中的return、throw語句失效。
總結一下這個小問題:
當程式執行try塊,catch塊時遇到return語句或者throw語句,這兩個語句都會導致該方法立即結束,所以系統並不會立即執行這兩個語句,而是 去尋找該異常處理流程中的finally塊,如果沒有finally塊,程式立即執行return語句或者throw語句,方法終止。如果有 finally塊,系統立即開始執行finally塊,只有當finally塊執行完成後,系統才會再次跳回來執行try塊、catch塊裡的 return或throw語句,如果finally塊裡也使用了return或throw等導致方法終止的語句,則finally塊已經終止了方法,不用 再跳回去執行try塊、catch塊裡的任何程式碼了。
綜上:儘量避免在finally塊裡使用return或throw等導致方法終止的語句,否則可能出現一些很奇怪的情況!
使用throws丟擲異常的思路是:當前方法不知道如何處理這種型別的異常,該異常應該由上一級呼叫者處理,如果main方法也不知道應該如何處理這種型別的異常,也可以使用使用throws宣告丟擲異常,該異常將交給JVM來處理。
JVM對異常的處理方法:列印異常跟蹤棧的資訊,並終止程式執行,所以有很多程式遇到異常後自動結束。