java简述对象的组合_Java程序运行和对象创建过程简述
Java中一個(gè)對象創(chuàng)建分為兩個(gè)步驟: 加載類,創(chuàng)建對象。
加載類是將所寫的程序.java文件編譯生成的.class文件加載到內(nèi)存中,保證了對象創(chuàng)建的預(yù)置環(huán)境。類加載完畢后才可以創(chuàng)建該類的對象。
第一步:加載類
1. 當(dāng)開始運(yùn)行一個(gè)類,虛擬機(jī)首先試圖訪問指定啟動(dòng)類的 .main() 方法,加載該類的 .class 文件。
2. 如果該類有父類,那么繼續(xù)加載其父類,以此類推,直到加載出所有與main入口類相關(guān)的類(它的父類,父類的父類等)。
3. 接著,從其頂級父類開始,對其static域按照順序進(jìn)行初始化!直至初始化完所有類的static域。>將static域放到靜態(tài)存儲區(qū)。
4. 至此類的加載工作完畢了,下面就進(jìn)入main函數(shù),執(zhí)行main函數(shù)。一般main函數(shù)中來創(chuàng)建類的對象,如果發(fā)現(xiàn)要?jiǎng)?chuàng)建的類沒有被加載,則繼續(xù)加載該類)
第二步:對象創(chuàng)建
1. 為對象獲取內(nèi)存,然后將內(nèi)存全部置為0,此時(shí)對象中的所有屬性都是被賦予0的默認(rèn)值(內(nèi)存為0時(shí)候的默認(rèn)值:null-對象引用,0-int,false-boolean...)> 在堆中生成對象所需空間,全部初始化為0,具體成員屬性值為堆上對應(yīng)內(nèi)存子塊--正是因?yàn)檫@種機(jī)制,所以java可以保證所有的類對象的屬性都會(huì)被初始化,但是局部不會(huì)被初始化。
這里需要注意的是:一個(gè)對象內(nèi)部組合了另一個(gè)對象,那么在堆中其實(shí)存的也是一個(gè)引用,這個(gè)引用指向被組合對象的堆內(nèi)存地址(另外再創(chuàng)建)。
當(dāng)引用在內(nèi)存的二進(jìn)制數(shù)據(jù)都為0的時(shí)候,他的表現(xiàn)形式是null;當(dāng)他指向的數(shù)據(jù)內(nèi)容內(nèi)存區(qū)數(shù)據(jù)都是0的時(shí)候,他的值為0,"",False等初始標(biāo)準(zhǔn)值。所謂初始化就是修改內(nèi)存區(qū)的二進(jìn)制數(shù)據(jù),因?yàn)閷ο笤趧?chuàng)建時(shí)候第一步就將內(nèi)存清0,所以保證了所有屬性都能至少被初始化為標(biāo)準(zhǔn)初值!
但是局部變量不一樣,你不初始化,只是申明,那么開辟的內(nèi)存區(qū)在棧中值會(huì)是一個(gè)未知數(shù)據(jù)(一旦使用該引用的話,使用的可能是你沒有初始化而瞎幾把亂指的地址)所以Java會(huì)代碼檢驗(yàn)的時(shí)候發(fā)現(xiàn)你使用了未初始化的引用,直接給予不通過,直接杜絕了這種可能性的發(fā)生。
綜上,Java中使用任何變量或引用,必須初始化,初始化就是將內(nèi)存中舊的二進(jìn)制數(shù)據(jù)要么清0,要么賦予你要賦的值!
2. 從頂級父類開始,按照申明順序?qū)⒔o頂級父類的非static的成員屬性初始化(static的只初始化一次在類加載階段)> 用屬性定義的值覆蓋0值。
3. 調(diào)用頂級父類的構(gòu)造函數(shù),如果有成員屬性初始化則覆蓋前一個(gè)申明時(shí)初始化值。> 構(gòu)造函數(shù)再次初始化,覆蓋前面申明時(shí)初始化。
4. 以此類推,將所有的父級(先初始化屬性,在調(diào)用構(gòu)造,一層一層的構(gòu)造完畢) 構(gòu)造完成
5. 最后,初始化當(dāng)前類的非static屬性,再調(diào)用當(dāng)前類的構(gòu)造函數(shù),完成所有初始化工作。
注意:
1、類中static部分是發(fā)生在類加載時(shí)期的,并且只初始化一次。因?yàn)轭愔患虞d一次,加載完后創(chuàng)建對象過程中不會(huì)再去初始化static部分的東西,所以之后根本不會(huì)再走那塊初始化代碼,又怎么初始化第二次呢?
2、static的優(yōu)先級是高于main函數(shù)執(zhí)行的,因?yàn)樗窃陬惣虞d時(shí)期初始化。當(dāng)static作用的東西都加載完了才執(zhí)行main,當(dāng)然main是第一個(gè)被使用的static方法,但是虛擬機(jī)只是找到這個(gè)方法的位置,并不會(huì)先去執(zhí)行里面的內(nèi)容。
2、對于類的普通成員屬性初始化三個(gè)步驟:先全初始化為0,再用申明時(shí)候初始化值進(jìn)行初始化,再調(diào)用構(gòu)造函數(shù)進(jìn)行初始化。
實(shí)例程序:(來源于Thinking in Java)
//: reusing/Beetle.java
// The full process of initialization.
import static net.mindview.util.Print.*;
class Insect {
private int i = 9;
protected int j;
Insect() {
print("i = " + i + ", j = " + j);
j = 39;
}
private static int x1 =
printInit("static Insect.x1 initialized");
static int printInit(String s) {
print(s);
return 47;
}
}
public class Beetle extends Insect {
private int k = printInit("Beetle.k initialized");
public Beetle() {
print("k = " + k);
print("j = " + j);
}
private static int x2 =
printInit("static Beetle.x2 initialized");
public static void main(String[] args) {
print("Beetle constructor");
Beetle b = new Beetle();
}
}/* Output:
static Insect.x1 initialized
static Beetle.x2 initialized //1.類加載和初始化靜態(tài)x1,x2:只會(huì)初始化一次!
Beetle constructor //2.進(jìn)入main函數(shù)
i = 9, j = 0
//3.new Beetle(),先初始化父類>申請父類內(nèi)存>初始化為0>初始化i=9,j=0>調(diào)用Insect()構(gòu)造函數(shù)>輸出ij值>初始化j=39
Beetle.k initialized //4.初始化子類>申請子類內(nèi)存>..>初始化k,輸出改行>調(diào)用構(gòu)造Beetle()>輸出下面的k,j
k = 47
j = 39
*///:~
總結(jié)
以上是生活随笔為你收集整理的java简述对象的组合_Java程序运行和对象创建过程简述的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java web项目目录报错_netde
- 下一篇: 12万吨核动力补给舰与航母的差异