Java中的靜態(tài)代碼塊與構(gòu)造代碼塊詳解
1、靜態(tài)代碼塊
1. 底層原理
靜態(tài)代碼塊在類的字節(jié)碼被加載到JVM時(shí)執(zhí)行,并且在整個(gè)JVM生命周期中只會(huì)執(zhí)行一次。
JVM在加載類時(shí),先加載類的字節(jié)碼,接著在類中查找靜態(tài)成員和靜態(tài)代碼塊。
所有的靜態(tài)代碼塊會(huì)按照它們?cè)陬愔卸x的順序依次執(zhí)行。
2. 執(zhí)行時(shí)機(jī)
靜態(tài)代碼塊的執(zhí)行時(shí)機(jī)是在類加載過(guò)程中。類加載通常發(fā)生在以下情況之一時(shí):
- 類的第一個(gè)實(shí)例被創(chuàng)建。
- 訪問類的第一個(gè)靜態(tài)成員(靜態(tài)變量或靜態(tài)方法)。
- 使用反射機(jī)制來(lái)加載類。
當(dāng)滿足上述任一條件時(shí),JVM會(huì)加載該類,并執(zhí)行類中的所有靜態(tài)代碼塊。
3. 作用
- 初始化靜態(tài)變量:可以在靜態(tài)代碼塊中對(duì)靜態(tài)變量進(jìn)行復(fù)雜的初始化操作。
- 執(zhí)行一次性設(shè)置:比如加載配置文件、初始化數(shù)據(jù)庫(kù)連接池等,僅需要在類加載時(shí)執(zhí)行一次的操作。
- 用于捕捉類的加載時(shí)間點(diǎn):有時(shí)我們希望在類加載時(shí)執(zhí)行某些邏輯,靜態(tài)代碼塊是一個(gè)非常合適的地方。
4. 示例
public class StaticBlock { static { System.out.println("靜態(tài)代碼塊 1 被執(zhí)行。"); } static int staticVar = initStaticVar(); static { System.out.println("靜態(tài)代碼塊 2 被執(zhí)行。"); } private static int initStaticVar() { System.out.println("靜態(tài)變量被初始化。"); return 1024; } public static void main(String[] args) { System.out.println("主方法被執(zhí)行。"); System.out.println("靜態(tài)變量staticVar的值為: " + staticVar); } }
運(yùn)行結(jié)果為:
靜態(tài)代碼塊 1 被執(zhí)行。
靜態(tài)變量被初始化。
靜態(tài)代碼塊 2 被執(zhí)行。
主方法被執(zhí)行。
靜態(tài)變量staticVar的值為: 1024
在這個(gè)示例中:
- 靜態(tài)代碼塊按照它們?cè)陬愔卸x的順序執(zhí)行。
- 靜態(tài)變量
staticVar
的初始化發(fā)生在第一個(gè)靜態(tài)代碼塊和第二個(gè)靜態(tài)代碼塊之間。 - 這些操作只在類首次加載時(shí)執(zhí)行一次。
2、構(gòu)造代碼塊
1. 底層原理
構(gòu)造代碼塊是在每次創(chuàng)建對(duì)象時(shí)執(zhí)行的。JVM在構(gòu)造對(duì)象的過(guò)程中,會(huì)在調(diào)用構(gòu)造方法之前執(zhí)行構(gòu)造代碼塊。
構(gòu)造代碼塊可以用于在對(duì)象創(chuàng)建時(shí)對(duì)實(shí)例變量進(jìn)行初始化,或者執(zhí)行一些在每次創(chuàng)建對(duì)象時(shí)需要執(zhí)行的代碼。
2. 執(zhí)行時(shí)機(jī)
每次創(chuàng)建對(duì)象時(shí),JVM首先會(huì)在堆內(nèi)存中分配對(duì)象的內(nèi)存,然后按照以下步驟執(zhí)行:
- 初始化實(shí)例變量為默認(rèn)值。
- 執(zhí)行構(gòu)造代碼塊,按它們?cè)陬愔卸x的順序執(zhí)行。
- 執(zhí)行構(gòu)造方法。
因此,構(gòu)造代碼塊的執(zhí)行是在構(gòu)造方法之前的,即使在構(gòu)造方法中進(jìn)行實(shí)例變量的賦值,構(gòu)造代碼塊中的代碼也會(huì)先于這些操作執(zhí)行。
3. 作用
- 實(shí)例變量的復(fù)雜初始化:構(gòu)造代碼塊適合用來(lái)進(jìn)行實(shí)例變量的復(fù)雜初始化操作,尤其是當(dāng)初始化邏輯需要在多個(gè)構(gòu)造方法中共享時(shí)。
- 每次創(chuàng)建對(duì)象時(shí)執(zhí)行的邏輯:構(gòu)造代碼塊中的代碼每次創(chuàng)建對(duì)象時(shí)都會(huì)執(zhí)行,所以可以用來(lái)在對(duì)象創(chuàng)建時(shí)執(zhí)行一些公共的邏輯。
4. 示例
public class ConstructBlock { { System.out.println("構(gòu)造代碼塊 1 被執(zhí)行。"); } int constructVar = initConstructVar(); { System.out.println("構(gòu)造代碼塊 2 被執(zhí)行。"); } private int initConstructVar() { System.out.println("成員變量被初始化。"); return 1024; } public ConstructBlock() { System.out.println("構(gòu)造方法被執(zhí)行。"); } public static void main(String[] args) { System.out.println("創(chuàng)建第一個(gè)對(duì)象:"); new ConstructBlock(); System.out.println("\n創(chuàng)建第二個(gè)對(duì)象:"); new ConstructBlock(); } }
運(yùn)行結(jié)果為:
創(chuàng)建第一個(gè)對(duì)象:
構(gòu)造代碼塊 1 被執(zhí)行。
成員變量被初始化。
構(gòu)造代碼塊 2 被執(zhí)行。
構(gòu)造方法被執(zhí)行。創(chuàng)建第二個(gè)對(duì)象:
構(gòu)造代碼塊 1 被執(zhí)行。
成員變量被初始化。
構(gòu)造代碼塊 2 被執(zhí)行。
構(gòu)造方法被執(zhí)行。
在這個(gè)示例中:
- 每次創(chuàng)建對(duì)象時(shí),構(gòu)造代碼塊和實(shí)例變量的初始化邏輯都會(huì)執(zhí)行。
- 無(wú)論你調(diào)用哪個(gè)構(gòu)造方法,構(gòu)造代碼塊都將被執(zhí)行,從而確保一些邏輯可以在所有構(gòu)造方法執(zhí)行前運(yùn)行。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
如何使用Resttemplate和Ribbon調(diào)用Eureka實(shí)現(xiàn)負(fù)載均衡
這篇文章主要介紹了如何使用Resttemplate和Ribbon調(diào)用Eureka實(shí)現(xiàn)負(fù)載均衡,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03spring cloud config分布式配置中心的高可用問題
本文給大家介紹spring cloud config分布式配置中心的高可用問題,通過(guò)整合Eureka來(lái)實(shí)現(xiàn)配置中心的高可用,需要的朋友參考下本文2018-01-01springboot 設(shè)置server.port不生效的原因及解決
這篇文章主要介紹了springboot 設(shè)置server.port不生效的原因及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08淺談Ribbon、Feign和OpenFeign的區(qū)別
這篇文章主要介紹了淺談Ribbon、Feign和OpenFeign的區(qū)別。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06Spring Boot 集成Shiro的多realm配置過(guò)程
這篇文章主要介紹了Spring Boot 集成Shiro的多realm配置,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10jvm垃圾回收GC調(diào)優(yōu)基礎(chǔ)原理分析
談到調(diào)優(yōu),這一定是針對(duì)特定場(chǎng)景、特定目的的事情, 對(duì)于 GC 調(diào)優(yōu)來(lái)說(shuō),首先就需要清楚調(diào)優(yōu)的目標(biāo)是什么?從性能的角度看,通常關(guān)注三個(gè)方面,內(nèi)存占用(footprint)、延時(shí)(latency)和吞吐量(throughput)2022-01-01詳解Java的內(nèi)置異常以及創(chuàng)建自定義異常子類的方法
這篇文章主要介紹了詳解Java的內(nèi)置異常以及創(chuàng)建自定義異常子類的方法,是Java入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-09-09安卓系統(tǒng)中實(shí)現(xiàn)搖一搖畫面振動(dòng)效果的方法
這篇文章主要介紹了安卓系統(tǒng)中實(shí)現(xiàn)搖一搖畫面振動(dòng)效果的方法,調(diào)用Android SDK中的SensorEventListener接口,需要的朋友可以參考下2015-07-07SpringBoot參數(shù)校驗(yàn)之@Valid的使用詳解
這篇文章主要通過(guò)示例為大家詳細(xì)介紹一下介紹了SpringBoot參數(shù)校驗(yàn)中@Valid的使用方法,文中的示例代碼講解詳細(xì),需要的可以參考一下2022-06-06