Java中關(guān)鍵字final finally finalize的區(qū)別介紹
這三個(gè)除了長(zhǎng)得像以外,好像沒(méi)什么聯(lián)系
1. final
final意為“最后的”,它是Java中的一個(gè)關(guān)鍵字。
final可以修飾屬性、方法、類。
1.1 final修飾屬性
從final的含義就不難理解用final修飾內(nèi)容的用意。final修飾屬性,就表示這個(gè)屬性是“最終的”,也就是不可更改的,換成我們熟悉的名詞,也就是“常量”。
private final double PI = 3.1415926; //被final修飾的屬性常常用大寫表示,全部大寫在idea的快捷鍵是ctrl+shift+u
此時(shí)如果再想修改這個(gè)值,就會(huì)報(bào)錯(cuò)。
final修飾的屬性可以通過(guò)多種方式進(jìn)行初始化,比如顯式初始化、代碼塊初始化、構(gòu)造方法初始化等等。
public class Test { private final int WIDTH = 10; //顯示初始化 private final int HEIGHT; private final int LEFT; { HEIGHT = 10; //代碼塊初始化 } public Test(){ LEFT = 10; //構(gòu)造方法初始化 } public Test(int n){ LEFT = n; //構(gòu)造方法初始化 } }
final修飾屬性經(jīng)常和static一起使用,表示全局常量 。
另外,final還可以修飾局部變量
public void test(final int NUMBER){ }
public void test(int number){ final int NUM = number; }
上文提到final修飾屬性的多種初始化方法,這里注意一點(diǎn),切記不要使用普通方法去初始化,當(dāng)然這種方式都不會(huì)編譯通過(guò)。因?yàn)閒inal引用的屬性在對(duì)象出現(xiàn)前就已經(jīng)存在了,調(diào)用方法賦值就太晚了。
1.2 final修飾方法
final修飾方法表示此方法不可重寫。套用含義上的理解,也就是“最終的方法”,也就是不可被修改的方法。
比如寫一個(gè)父類
class ParentClass{ public final void finalMethod(){ } }
嘗試在子類中重寫這個(gè)方法,就會(huì)報(bào)錯(cuò)。
1.3 final修飾類
final修飾類,套用含義上的理解,“最終的類”意為不可修改的類,表示該類不可被繼承,因?yàn)槔^承就可以重寫方法、擴(kuò)展功能,是對(duì)現(xiàn)有類的修改。
聲明一個(gè)final的類
final class ParentClass{ }
嘗試去繼承這個(gè)類,就會(huì)報(bào)錯(cuò)
2. finally
finally用于異常處理,try-catch-finally,finally表示最終會(huì)執(zhí)行的功能塊。finally包裹的代碼塊一定會(huì)執(zhí)行。(注意這個(gè)“一定會(huì)執(zhí)行”,后文有坑)
try{ //可能出現(xiàn)異常的代碼 } catch(異常類型1 變量名1){ //處理異常的方式1 } catch(異常類型2 變量名2){ //處理異常的方式2 } finally{ //一定會(huì)執(zhí)行的代碼 }
舉一個(gè)例子
@Test public void test(){ try{ int a = 10; int b = 0; System.out.println(a/b); } catch (ArithmeticException e){ System.out.println("處理方式1"); } catch (Exception e){ System.out.println("處理方式2"); } finally { System.out.println("執(zhí)行finally"); } }
執(zhí)行結(jié)果:
注意以下三點(diǎn):
- finally是可選的,在try-catch結(jié)構(gòu)中不使用finally沒(méi)有任何問(wèn)題
- finally聲明的代碼是一定會(huì)執(zhí)行的
- 像數(shù)據(jù)庫(kù)連接、輸入輸出流、網(wǎng)絡(luò)Socket… JVM是不能自動(dòng)回收的,所以常常在可能存在異常的代碼中手動(dòng)在finally釋放掉這些資源
擴(kuò)展-finally和return誰(shuí)會(huì)先執(zhí)行?
上文多次提到“finally聲明的代碼是一定會(huì)執(zhí)行的”,那么在try或者catch中出現(xiàn)了return,那么誰(shuí)會(huì)先執(zhí)行?
執(zhí)行以下代碼,會(huì)輸出什么?
private int finallyTest(){ try{ int a = 10; int b = 0; System.out.println(a/b); return 1; } catch (Exception e){ return 2; } finally { System.out.println("執(zhí)行finally"); } }
調(diào)用一下
@Test public void test(){ int num = finallyTest(); System.out.println(num); }
結(jié)果如下圖,也就是即使在catch中有return語(yǔ)句,也要等待finally聲明的代碼執(zhí)行完再return出去。
3. finalize
finalize翻譯為“使結(jié)束”,它是一個(gè)方法,是每個(gè)類默認(rèn)存在的方法。
打開(kāi)Object類的源碼,就可以找到finalize()方法
finalize()方法用于GC回收,finalize是本文最難理解的概念,要真正理解finalize()方法,就要深入理解GC回收機(jī)制,而本文的側(cè)重點(diǎn)并不在于解釋GC回收機(jī)制,所以只會(huì)簡(jiǎn)單地描述一下finalize()方法的使用場(chǎng)景,讀者如果感興趣,請(qǐng)自行查找相關(guān)的文章。
在Java的內(nèi)存管理中,使用可達(dá)性分析算法來(lái)判斷對(duì)象是否存活,基本思路是通過(guò)一系列稱為“GC Roots”的跟對(duì)象作為起始節(jié)點(diǎn),根據(jù)引用關(guān)系向下搜索,如果某些對(duì)象到GC Roots之間沒(méi)有任何引用關(guān)系,則證明此對(duì)象是不能被再使用的,就有可能去回收這一塊內(nèi)存了。下圖中,雖然object5、object6、object7之間有引用關(guān)系,但是到GC Roots沒(méi)有任何途徑,則這些對(duì)象仍在回收的范圍內(nèi)。
生存還是死亡?
即使經(jīng)過(guò)可達(dá)性分析算法判定為不可達(dá)的對(duì)象,也不是非要回收不可,要真正回收一個(gè)內(nèi)存空間,至少需要兩次的不可達(dá)判定。經(jīng)過(guò)第一次不可達(dá)判定,隨后要進(jìn)行一個(gè)篩選,篩選的條件是該對(duì)象是否有必要執(zhí)行finalize()方法。假如待回收的對(duì)象沒(méi)有重寫finalize()方法,或者finalize()方法被JVM調(diào)用過(guò)(每個(gè)對(duì)象的finalize()方法只能被JVM調(diào)用一次),這兩種情況都會(huì)被虛擬機(jī)認(rèn)為是“沒(méi)有必要執(zhí)行finalize()方法”,那么在經(jīng)過(guò)幾輪不可達(dá)標(biāo)記后,該對(duì)象被真正地回收掉。
如果該對(duì)象被認(rèn)定為“有必要執(zhí)行finalize()方法”,則稍后會(huì)被低調(diào)度優(yōu)先級(jí)的線程去執(zhí)行finalize()方法,而重寫的finalize()方法有可能完成一次對(duì)象的“自救”,比如將this賦給某個(gè)屬性,那么在后續(xù)標(biāo)記時(shí)會(huì)被判定為“可達(dá)”,那么JVM就不會(huì)回收這個(gè)對(duì)象。
盡管finalize()方法有著特殊的使用場(chǎng)景,但是永遠(yuǎn)也不要顯式調(diào)用某個(gè)對(duì)象的finalize()方法,應(yīng)該交給GC回收機(jī)制調(diào)用。
到此這篇關(guān)于Java中關(guān)鍵字final finally finalize的區(qū)別介紹的文章就介紹到這了,更多相關(guān)Java關(guān)鍵字final finally finalize內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot使用Value注解給靜態(tài)變量賦值的方法
這篇文章主要介紹了Spring Boot使用Value注解給靜態(tài)變量賦值的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-07-07Java實(shí)現(xiàn)滑動(dòng)驗(yàn)證碼的示例代碼
這篇文章主要介紹了Java實(shí)現(xiàn)滑動(dòng)驗(yàn)證碼的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01Java多線程和并發(fā)基礎(chǔ)面試題(問(wèn)答形式)
多線程和并發(fā)問(wèn)題是Java技術(shù)面試中面試官比較喜歡問(wèn)的問(wèn)題之一。在這里,從面試的角度列出了大部分重要的問(wèn)題,感興趣的小伙伴們可以參考一下2016-06-06從0到1學(xué)SpringCloud之SpringCloud?gateway網(wǎng)關(guān)路由配置示例詳解
Spring?Cloud?Gateway的目標(biāo)提供統(tǒng)一的路由方式且基于Filter?鏈的方式提供了網(wǎng)關(guān)基本的功能,?例如:安全、監(jiān)控、指標(biāo)和限流?,這篇文章主要介紹了從0到1學(xué)SpringCloud之SpringCloud?gateway網(wǎng)關(guān)路由配置示例詳解,需要的朋友可以參考下2023-04-04Java深入淺出掌握SpringBoot之MVC自動(dòng)配置原理篇
在進(jìn)行項(xiàng)目編寫前,我們還需要知道一個(gè)東西,就是SpringBoot對(duì)我們的SpringMVC還做了哪些配置,包括如何擴(kuò)展,如何定制,只有把這些都搞清楚了,我們?cè)谥笫褂貌艜?huì)更加得心應(yīng)手2021-10-10SpringBoot結(jié)果封裝和異常攔截的實(shí)現(xiàn)示例
SpringBoot 項(xiàng)目中,我們通常需要將結(jié)果數(shù)據(jù)封裝成特定的格式,以方便客戶端進(jìn)行處理,本文主要介紹了SpringBoot?優(yōu)雅的結(jié)果封裝和異常攔截,感興趣的可以了解一下2023-08-08spring-cloud-gateway動(dòng)態(tài)路由的實(shí)現(xiàn)方法
這篇文章主要介紹了spring-cloud-gateway動(dòng)態(tài)路由的實(shí)現(xiàn)方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01Java的springcloud Sentinel是什么你知道嗎
這篇文章主要介紹了Java之springcloud Sentinel案例講解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08