日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

java在初始化过程_Java初始化过程

發(fā)布時(shí)間:2025/4/5 java 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java在初始化过程_Java初始化过程 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這篇文章主要講解Java在創(chuàng)建對(duì)象的時(shí)候,初始化的順序。主要從以下幾個(gè)例子中講解:

繼承關(guān)系中初始化順序

初始化塊與構(gòu)造器的順序

已經(jīng)加載過(guò)的類的初始化順序

加載父類,會(huì)不會(huì)加載子類

創(chuàng)建子類對(duì)象會(huì)不會(huì)創(chuàng)建父類對(duì)象

例子1——繼承關(guān)系中初始化順序

先看簡(jiǎn)單的情況,看下面的例子:

public class Father {

public String fatherVar = "父類構(gòu)造塊初始化";

public static int fatherStaticVar;

public int i;

static {

int i = 100;

System.out.println("父類靜態(tài)塊初始化,i的值為" + i);

System.out.println("父類靜態(tài)變量初始化,fatherStaticVar的值為" + fatherStaticVar);

}

{

System.out.println(fatherVar);

}

public Father(){

System.out.println("父類構(gòu)造函數(shù)的初始化,i的值" + i);

}

}

public class Son extends Father {

public String sonVar = "子類構(gòu)造塊初始化";

public static int sonStaticVar;

public int i;

static {

int i = 101;

System.out.println("子類靜態(tài)塊初始化,i的值為" + i);

System.out.println("子類靜態(tài)變量初始化,sonStaticVar的值為" + sonStaticVar);

}

{

System.out.println(sonVar);

}

public Son(){

super();

System.out.println("子類構(gòu)造函數(shù)的初始化,i的值" + i);

}

public static void main(String[] args) {

new Son();

}

}

其執(zhí)行的結(jié)果如下:

父類靜態(tài)塊初始化,i的值為100

父類靜態(tài)變量初始化,fatherStaticVar的值為0

子類靜態(tài)塊初始化,i的值為101

子類靜態(tài)變量初始化,sonStaticVar的值為0

父類構(gòu)造塊初始化

父類構(gòu)造函數(shù)的初始化,i的值0

子類構(gòu)造塊初始化

子類構(gòu)造函數(shù)的初始化,i的值0

按照結(jié)果,我們可以知道在有繼承的時(shí)候,雖然是創(chuàng)建一個(gè)Son對(duì)象,但是JVM發(fā)現(xiàn)Son對(duì)象的類還沒(méi)有裝載,而Son類又繼承自Father類,只有加載了Father類,才能加載Son類。于是加載Father類的時(shí)候,就會(huì)初始化一切靜態(tài)變量和靜態(tài)塊。所以上文結(jié)果中第一行和第二行是父類靜態(tài)變量和靜態(tài)塊初始化的結(jié)果,然后加載完Father類之后,又會(huì)加載Son類,同樣是初始化Son類的靜態(tài)塊和靜態(tài)變量,出現(xiàn)上文中第三行和第四行的結(jié)果。等這個(gè)2個(gè)類都加載完了,才開始創(chuàng)建Son對(duì)象,因?yàn)镾on對(duì)象,顯示調(diào)用了Father類的構(gòu)造器,所以先執(zhí)行Father類的構(gòu)造器,出現(xiàn)第五行和第六行的結(jié)果,等Father類構(gòu)造器執(zhí)行完了,才執(zhí)行后續(xù)Son構(gòu)造器的內(nèi)容,所以最后出現(xiàn)了第七行和第八行的結(jié)果。

例子2——初始化塊與構(gòu)造器的順序

在上面的例子中,有2個(gè)語(yǔ)句塊叫初始化塊。在上文的結(jié)果中是初始化塊的執(zhí)行是先于構(gòu)造器的,現(xiàn)在看一下把初始化塊的內(nèi)容放到構(gòu)造器下面,會(huì)是什么的結(jié)果

public class InitBlock {

public InitBlock(){

System.out.println("構(gòu)造器在執(zhí)行......");

}

{

System.out.println("初始化塊1在執(zhí)行......");

}

{

System.out.println("初始化塊2在執(zhí)行......");

}

public static void main(String[] args) {

new InitBlock();

}

}

結(jié)果如下:

初始化塊1在執(zhí)行......

初始化塊2在執(zhí)行......

構(gòu)造器在執(zhí)行......

很顯然,無(wú)論初始化塊寫在哪個(gè)地方,都是先于構(gòu)造器執(zhí)行的,但是初始化塊之間的順序是前面的先初始化,后面在初始化。

例子3——已經(jīng)加載過(guò)的類的初始化順序

更改一下例子1中的main方法,改成如下:

public static void main(String[] args) {

new Father();

System.out.println("=============");

new Son();

}

結(jié)果如下:

父類靜態(tài)塊初始化,i的值為100

父類靜態(tài)變量初始化,fatherStaticVar的值為0

子類靜態(tài)塊初始化,i的值為101

子類靜態(tài)變量初始化,sonStaticVar的值為0

父類構(gòu)造塊初始化

父類構(gòu)造函數(shù)的初始化,i的值0

=============

父類構(gòu)造塊初始化

父類構(gòu)造函數(shù)的初始化,i的值0

子類構(gòu)造塊初始化

子類構(gòu)造函數(shù)的初始化,i的值0

結(jié)果很有意思,創(chuàng)建父類對(duì)象的時(shí)候,加載Father類,出現(xiàn)第一行和第二行的結(jié)果,但是這個(gè)竟然會(huì)還把子類的靜態(tài)變量和靜態(tài)塊初始化?這個(gè)原因,例子4在說(shuō)。 最后執(zhí)行父類的構(gòu)造器創(chuàng)建父類對(duì)象。當(dāng)再創(chuàng)建子類的時(shí)候,發(fā)現(xiàn)父類和子類已經(jīng)加載過(guò)了,所以不會(huì)再加載Father和Son類,只會(huì)調(diào)用父類的構(gòu)造器,再執(zhí)行后續(xù)子類構(gòu)造器的內(nèi)容,創(chuàng)建子類。

例子4——加載父類,會(huì)不會(huì)加載子類

用一個(gè)嶄新的例子來(lái)看看上面,創(chuàng)建父類的時(shí)候,為什么會(huì)打印出子類靜態(tài)初始化執(zhí)行的結(jié)果。

public class StaticFather {

static{

System.out.println("父類靜態(tài)初始化塊");

}

}

public class StaticSon extends StaticFather{

static {

System.out.println("子類靜態(tài)初始化塊");

}

}

public class Test {

public static void main(String[] args) {

new StaticFather();

}

}

結(jié)果如下:

父類靜態(tài)初始化塊

這次就不會(huì)創(chuàng)建父類的時(shí)候,加載子類。例子3之所以出現(xiàn)這個(gè)原因 是因?yàn)閙ain函數(shù)在子類中寫的,要執(zhí)行main函數(shù)必須要加載子類。只會(huì)加載子類之前要先加載父類,因?yàn)椴患虞d父類,只加載子類,怎么讓子類調(diào)用父類的方法和變量。但是加載父類不會(huì)加載子類,反正父類也調(diào)用不了子類的方法。

例子5——?jiǎng)?chuàng)建子類對(duì)象會(huì)不會(huì)創(chuàng)建父類對(duì)象

做個(gè)實(shí)驗(yàn),看一下創(chuàng)建子類對(duì)象的時(shí)候,到底會(huì)不會(huì)創(chuàng)建一個(gè)父類對(duì)象,先說(shuō)結(jié)論:不會(huì)。從道理上講,如果創(chuàng)建任何一個(gè)對(duì)象都要?jiǎng)?chuàng)建出一個(gè)他的父類對(duì)象的話,那么整個(gè)JVM虛擬機(jī)都是Object對(duì)象??聪旅娴膶?shí)驗(yàn):

public class ObjectFather {

public void getInfo(){

System.out.println(getClass().toString());

}

}

public class ObjectSon extends ObjectFather{

public ObjectSon(){

super();

super.getInfo();

}

public static void main(String[] args) {

new ObjectSon();

}

}

結(jié)果如下:

class com.byhieg.init.ObjectSon

可以看出來(lái),創(chuàng)建子類對(duì)象時(shí)那個(gè)父類的Class還是子類的,也就是說(shuō)創(chuàng)建子類對(duì)象并沒(méi)有創(chuàng)建一個(gè)父類的對(duì)象,只是說(shuō)調(diào)用了父類的構(gòu)造器,對(duì)父類的屬性進(jìn)行初始化,并且給子類提供了一個(gè)super指示器去調(diào)用父類中那些變量和方法。

更詳細(xì)的說(shuō),new一個(gè)對(duì)象實(shí)際上是通過(guò)一個(gè)new指令開辟一個(gè)空間,來(lái)存放對(duì)象。在new ObjectSon()的時(shí)候,就只有一個(gè)new指令,只會(huì)開辟一個(gè)空間,所謂初始化父類等等,都是在這個(gè)空間中有一個(gè)特殊的區(qū)域來(lái)存放這些數(shù)據(jù),而super關(guān)鍵字就是提供了訪問(wèn)這個(gè)特殊區(qū)域的方法,通過(guò)super去訪問(wèn)這個(gè)特殊區(qū)域。

還可以比較super和this的hashcode來(lái)判斷,結(jié)果必然是兩者的hashcode是一致的。

總結(jié)

至此,Java初始化的講解到結(jié)束了,基本了覆蓋了絕大多數(shù)情況中的初始化。

總結(jié)

以上是生活随笔為你收集整理的java在初始化过程_Java初始化过程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。