摘要:靜態(tài)塊代碼初始化其實(shí),整個(gè)靜態(tài)代碼塊可以看作是一個(gè)靜態(tài)成員。和普通的非靜態(tài)成員初始化一樣,它的執(zhí)行也發(fā)生在構(gòu)造器調(diào)用之前,并且每當(dāng)創(chuàng)建對(duì)象之前都會(huì)調(diào)用。口繼承中涉及的初始化大的原則是沒有父類,就沒子類。
這個(gè)教程,咱們來對(duì)Java中設(shè)計(jì)到的初始化規(guī)則,或者說初始化順序,來做一下匯總,這里我基本上把Java中,默認(rèn)初始化,靜態(tài)成員初始化,非靜態(tài)成員初始化,靜態(tài)代碼塊,非靜態(tài)代碼塊,以及繼承中所涉及到的初始化,都涵蓋全了。希望你看到這個(gè)教程,能有所收獲。(?′?`?)
默認(rèn)初始化在Java中,一個(gè)類的數(shù)據(jù)成員(成員變量)如果沒有指定初始化,那么Java會(huì)對(duì)其執(zhí)行默認(rèn)初始化。
基本類型初始化默認(rèn)值為0,boolean為false,字符串或者對(duì)象引用初始化為null。這部分比較簡(jiǎn)單,看下面這個(gè)小列子,相信你應(yīng)該能直接看出來最后運(yùn)行的結(jié)果。(<_<)
public class InitialValues { boolean t; char c; short s; int i; long l; float f; double d; String str; InitialValues reference; void printInitialValues() { System.out.printf("%-10s %-5s ", "boolean:", t); System.out.printf("%-10s %-5s ", "char:", c); System.out.printf("%-10s %-5s ", "short:", s); System.out.printf("%-10s %-5s ", "int:", i); System.out.printf("%-10s %-5s ", "long:", l); System.out.printf("%-10s %-5s ", "float:", f); System.out.printf("%-10s %-5s ", "double:", d); System.out.printf("%-10s %-5s ", "String:", str); System.out.printf("%-10s %-5s ", "reference:", reference); } public static void main(String[] args) { InitialValues iv = new InitialValues(); iv.printInitialValues(); } }
// Output ---------------- boolean: false char: short: 0 int: 0 long: 0 float: 0.0 double: 0.0 String: null reference: null非靜態(tài)成員初始化順序
在一個(gè)類中,非靜態(tài)成員的初始化,發(fā)生在任何方法(包括構(gòu)造器)被調(diào)用之前。并且它們定義的順序,決定了初始化的順序。來看下面這個(gè)小程序,這里的類,我都用的通用的無(wú)實(shí)際意義的類,這樣能讓咱們把注意力放在代碼邏輯上。這個(gè)小程序,我給你提點(diǎn)要求:你捋一下代碼的邏輯,看看能不能直接寫出來最后的運(yùn)行結(jié)果。完了把你寫的結(jié)果和我后面給你的答案對(duì)比一下,看看能不能搞對(duì)。最后你自己最好能敲敲程序運(yùn)行一下。( ??⊿??)?
class XXX { XXX(String s){ System.out.println("XXX > " + s); } } class AAA { XXX x001 = new XXX("001"); AAA() { System.out.println("AAA"); XXX x004 = new XXX("004"); } XXX x002 = new XXX("002"); void fff() { System.out.println("fffffffff"); } XXX xxx003 = new XXX("003"); } public class Initialization { public static void main(String[] args) { AAA aaa = new AAA(); aaa.fff(); } }
// Output --------- XXX > 001 XXX > 002 XXX > 003 AAA XXX > 004 fffffffff靜態(tài)成員初始化及對(duì)象的創(chuàng)建過程
以名為YYY的類舉例:
當(dāng)該類的靜態(tài)方法(包括main()和構(gòu)造器,構(gòu)造器實(shí)際上也是靜態(tài)方法)或者靜態(tài)成員被調(diào)用或訪問時(shí),Java虛擬機(jī)將載入類所對(duì)應(yīng)的YYY.class文件,并創(chuàng)建其Class類對(duì)象,然后該類所有的靜態(tài)成員將執(zhí)行初始化。并且靜態(tài)成員初始化只執(zhí)行這一次。
靜態(tài)初始化完成后,該類就做好了創(chuàng)建對(duì)象的準(zhǔn)備。當(dāng)調(diào)用new YYY()創(chuàng)建對(duì)象的時(shí)候,首先在堆內(nèi)存上為YYY對(duì)象分配空間,然后執(zhí)行默認(rèn)初始化(基本類型初始化為0,引用類型初始化為null)。
之后,按照非靜態(tài)成員定義順序,進(jìn)行指定初始化。
最后執(zhí)行構(gòu)造器,完成對(duì)象的創(chuàng)建。
還是和上面同樣的要求,先捋代碼邏輯,再手寫結(jié)果。 (`?ω?′)ゞ
class XXX { XXX(String s){ System.out.println("XXX > " + s); } void xox(String s){ System.out.println("xox : " + s); } } class AAA { XXX x001 = new XXX("001"); static XXX x002 = new XXX("002"); AAA() { System.out.println("AAA"); x002.xox("002"); } void aaa() { System.out.println("aaa"); } } class BBB { static XXX x003 = new XXX("003"); XXX x004 = new XXX("004"); BBB(){ System.out.println("BBB"); x004.xox("004"); } void bbb(){System.out.println("bbb");} } public class Initialization { public static void main(String[] args) { System.out.println("*********"); new AAA(); System.out.println("========="); new BBB(); a002.aaa(); b002.bbb(); } AAA a001 = new AAA(); static AAA a002 = new AAA(); static AAA a003= new AAA(); BBB b001 = new BBB(); static BBB b002 = new BBB(); static BBB b003 = new BBB(); }
// Output --------- XXX > 002 XXX > 001 AAA xox : 002 XXX > 001 AAA xox : 002 XXX > 003 XXX > 004 BBB xox : 004 XXX > 004 BBB xox : 004 ********* XXX > 001 AAA xox : 002 ========= XXX > 004 BBB xox : 004 aaa bbb靜態(tài)塊代碼初始化
其實(shí),整個(gè)static { 靜態(tài)代碼塊 } 可以看作是一個(gè)靜態(tài)成員。當(dāng)一個(gè)類需要執(zhí)行靜態(tài)初始化時(shí),該類中的靜態(tài)成員初始化和靜態(tài)代碼塊,會(huì)按照先后定義的順序執(zhí)行。當(dāng)然,這個(gè)流程也是就執(zhí)行這一次。?⊙□⊙╱ 還是老要求......
class XXX { XXX(String s){ System.out.println("XXX > " + s); } } class AAA { XXX x001 = new XXX("001"); static XXX x002 = new XXX("002"); static XXX x003, x004; static { System.out.println("*********"); x003 = new XXX("003"); x004 = new XXX("004"); XXX x005 = new XXX("005"); System.out.println("========="); /**System.out.println(x006);*/ } static XXX x006 = new XXX("006"); XXX x007 = new XXX("007"); AAA() { System.out.println("AAA"); } } public class Initialization { static AAA aaa = new AAA(); public static void main(String[] args) { new AAA(); } }
// Output --------- XXX > 002 ********* XXX > 003 XXX > 004 XXX > 005 ========= XXX > 006 XXX > 001 XXX > 007 AAA XXX > 001 XXX > 007 AAA 假如把上面/**System.out.println(x006);*/注釋掉的代碼解除注釋,再運(yùn)行程序,會(huì)發(fā)生什么情況?非靜態(tài)代碼塊初始化
{ 非靜態(tài)代碼塊 },可以看作一個(gè)非靜態(tài)成員。涉及非靜態(tài)初始化,也會(huì)執(zhí)行它。和普通的非靜態(tài)成員初始化一樣,它的執(zhí)行也發(fā)生在構(gòu)造器調(diào)用之前,并且每當(dāng)創(chuàng)建對(duì)象之前都會(huì)調(diào)用。
稍微修改下上面的例子,把靜態(tài)代碼塊前面的static關(guān)鍵字去掉,并把里面的注釋行釋放,并添加一行打印語(yǔ)句,如下,對(duì)比兩個(gè)例子輸出結(jié)果。(=??口??=)
class XXX { XXX(String s){ System.out.println("XXX > " + s); } } class AAA { XXX x001 = new XXX("001"); static XXX x002 = new XXX("002"); static XXX x003, x004; { System.out.println("*********"); x003 = new XXX("003"); x004 = new XXX("004"); XXX x005 = new XXX("005"); System.out.println("========="); System.out.println(x006); System.out.println(x001); } static XXX x006 = new XXX("006"); XXX x007 = new XXX("007"); AAA() { System.out.println("AAA"); } } public class Initialization { static AAA aaa = new AAA(); public static void main(String[] args) { new AAA(); } }
// Output ------------- XXX > 002 XXX > 006 XXX > 001 ********* XXX > 003 XXX > 004 XXX > 005 ========= XXX@1540e19d XXX@677327b6 XXX > 007 AAA XXX > 001 ********* XXX > 003 XXX > 004 XXX > 005 ========= XXX@1540e19d XXX@14ae5a5 XXX > 007 AAA繼承中涉及的初始化
大的原則是:沒有父類,就沒子類。初始化,當(dāng)然要先初始化父類,再初始化子類。
繼承中如果同時(shí)涉及到靜態(tài)初始化和非靜態(tài)初始化。初始化的執(zhí)行流程分兩步走:
(1)先執(zhí)行靜態(tài)初始化。且先靜態(tài)初始化父類,然后再靜態(tài)初始化子類。(這一步同樣就執(zhí)行一次)
(2)父類執(zhí)行非靜態(tài)初始化,然后調(diào)用構(gòu)造方法。接著子類執(zhí)行非靜態(tài)初始化,然后調(diào)用構(gòu)造方法。接著下一個(gè)子類......以此類推到最后一個(gè)子類。 (??ω?? 」∠)
class XXX { XXX(String s){ System.out.println("XXX > " + s); } } class AAA { XXX x001 = new XXX("001"); static XXX x002 = new XXX("002"); AAA() { System.out.println("AAA"); } { System.out.println("*********"); XXX x003 = new XXX("003"); } static XXX x004; static { System.out.println("========="); x004 = new XXX("004"); } static XXX x005 = fff("005"); static XXX fff(String s) { System.out.println("fffffffff"); return new XXX(s); } } class BBB extends AAA { static XXX x006 = new XXX("006"); XXX x007= new XXX("007"); { System.out.println("+++++++++"); XXX x008 = new XXX("008"); } static XXX x009; static { System.out.println("$$$$$$$$$"); x009 = new XXX("009"); } BBB(){ System.out.println("BBB"); } static XXX x010 = fff("010"); } public class Initialization { public static void main(String[] args) { new BBB(); new BBB(); } }
// Output --------- XXX > 002 ========= XXX > 004 fffffffff XXX > 005 XXX > 006 $$$$$$$$$ XXX > 009 fffffffff XXX > 010 XXX > 001 ********* XXX > 003 AAA XXX > 007 +++++++++ XXX > 008 BBB XXX > 001 ********* XXX > 003 AAA XXX > 007 +++++++++ XXX > 008 BBB
拓展一下,假如把上面的父類AAA改為抽象類,運(yùn)行結(jié)果還一樣嗎?自己求證一下吧。
好,暫時(shí)先寫這么多,希望多多少少幫到了你點(diǎn)什么,后面我想到有需要補(bǔ)充的,我再更新帖子吧。??ヽ(?▽?)ノ?
============================================================================
有條件的小伙伴,可以給打賞點(diǎn)兒支持下,給我些鼓勵(lì)繼續(xù)寫下去。 (?′?`??)??
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/76368.html
摘要:總結(jié)動(dòng)態(tài)代理的相關(guān)原理已經(jīng)講解完畢,接下來讓我們回答以下幾個(gè)思考題。 【干貨點(diǎn)】 此處是【好好面試】系列文的第12篇文章。文章目標(biāo)主要是通過原理剖析的方式解答Aop動(dòng)態(tài)代理的面試熱點(diǎn)問題,通過一步步提出問題和了解原理的方式,我們可以記得更深更牢,進(jìn)而解決被面試官卡住喉嚨的情況。問題如下 SpringBoot默認(rèn)代理類型是什么 為什么不用靜態(tài)代理 JDK動(dòng)態(tài)代理原理 CGLIB動(dòng)態(tài)代理...
摘要:后來知道有了院賽,學(xué)長(zhǎng)說刷院和杭電就可,我就一直刷院,到最后比賽前院的前五十道基本做完,杭電也弄了十來道,就這樣草草參加比賽了。 博客主頁(yè): https://b...
摘要:微信在上一個(gè)大版本中將公眾號(hào)內(nèi)容的展示更改為信息流模式。克制的努力在本人看來,微信的產(chǎn)品思維真得堪稱楷模。你可以仿照微信來搞一個(gè)公眾號(hào),但如果不懂這些底層的邏輯,即便是輸了都不知道輸在哪里。 微信在上一個(gè)大版本中將公眾號(hào)內(nèi)容的展示更改為信息流模式。剛開始還有些不習(xí)慣,也不明白為什么要這樣做。在使用了一段時(shí)間之后,慢慢也就習(xí)慣了。但在使用的某一瞬間,潛意識(shí)中有一個(gè)疑惑:同樣是推文,為什么...
摘要:與此相對(duì),強(qiáng)類型語(yǔ)言的類型之間不一定有隱式轉(zhuǎn)換。三為什么是弱類型弱類型相對(duì)于強(qiáng)類型來說類型檢查更不嚴(yán)格,比如說允許變量類型的隱式轉(zhuǎn)換,允許強(qiáng)制類型轉(zhuǎn)換等等。在中,加性運(yùn)算符有大量的特殊行為。 從++[[]][+[]]+[+[]]==10?深入淺出弱類型JS的隱式轉(zhuǎn)換 本文純屬原創(chuàng)? 如有雷同? 純屬抄襲? 不甚榮幸! 歡迎轉(zhuǎn)載! 原文收錄在【我的GitHub博客】,覺得本文寫的不算爛的...
閱讀 2168·2021-11-24 09:39
閱讀 2781·2021-07-29 13:49
閱讀 2322·2019-08-29 14:15
閱讀 2233·2019-08-29 12:40
閱讀 3312·2019-08-26 13:42
閱讀 632·2019-08-26 12:13
閱讀 2065·2019-08-26 11:41
閱讀 3345·2019-08-23 18:32