###############################
今天總結一下,new對象的初始化過程。
###############################
首先,當不含static成員時,先看一下案例圖:
如圖所示,我們先定義相關類,Building,House(繼承Building),Villa(繼承House),同時,House有成員變量LivingRoom,LivingRoom有成員變量Bed和Desk。
具體代碼實現如下:
1 //建築 2 class Building { 3 public Building() { 4 System.out.println("Building"); 5 } 6 } 7 //房子 8 class House extends Building{ 9 public LivingRoom livingRoom = new LivingRoom();//卧室 10 public House() { 11 System.out.println("House"); 12 } 13 } 14 //別墅 15 class Villa extends House{ 16 public Villa () { 17 System.out.println("Villa"); 18 } 19 } 20 //卧室 21 class LivingRoom { 22 public Bed bedFirst = new Bed();//床 23 public Desk deskFirst = new Desk();//桌子 24 25 public LivingRoom () { 26 System.out.println("LivingRoom"); 27 } 28 } 29 //床 30 class Bed { 31 public Bed () { 32 System.out.println("Bed"); 33 } 34 } 35 //桌子 36 class Desk { 37 public Desk () { 38 System.out.println("Desk"); 39 } 40 } 41 此時,我們new Villa(): 42 public class InitializeDemo { 43 @Test 44 public void testInitialize() { 45 Villa villa = new Villa(); 46 } 47 } 48 執行結果為: 49 Building 50 Bed 51 Desk 52 LivingRoom 53 House 54 Villa
在此案例中,我們在創建Villa對象時,會先試着創建Villa的父類House的對象,但House也有父類Building,Building還有父類object。因此,實際上,本類會先創建object對象並初始化,在object對象創建並初始化后,會創建building對象,building對象沒有成員變量,所以直接執行構造器,打印出building。
接着,開始創建house對象,house對象有成員變量livingRoom,因此,會先初始化livingRoom,創建livingRoom時,也會先創建livingRoom的父類object對象並初始化沒其次再創建livingRoom實例,livingroom同樣有兩個成員變量bed和desk,因而會按兩個成員變量的定義順序,先后創建bed和desk。初始化成員變量成功后,執行livingroom的構造器,打印livingroom。初始化livingroom成功后,開始執行house的構造器,打印house。
最后,在house初始化成功后,執行了Villa的構造器,打印出Villa。
初始化成功。
其次,當有static成員時
1 class Family { 2 Family (Class className) { 3 System.out.println("創建Family對象"); 4 System.out.println(className.getName()); 5 } 6 } 7 class Person { 8 Person() { 9 System.out.println("創建Person對象"); 10 } 11 public static Family family = new Family(Person.class); 12 static { 13 System.out.println("執行Person靜態代碼塊"); 14 } 15 { 16 System.out.println("執行Person代碼塊"); 17 } 18 } 19 public class Student extends Person { 20 public Student() { 21 System.out.println("創建student對象"); 22 } 23 { 24 System.out.println("執行Student代碼塊"); 25 } 26 static { 27 System.out.println("執行Student靜態代碼塊"); 28 } 29 public static Family staticFamily = new Family(Student.class); 30 @Test 31 public void test() { 32 System.out.println("============="); 33 } 34 public Family family = new Family(Student.class); 35 } 36 執行結果: 37 創建Family對象 38 com.tca.thinkInJava.chap7.Person 39 執行Person靜態代碼塊 40 執行Student靜態代碼塊 41 創建Family對象 42 com.tca.thinkInJava.chap7.Student 43 執行Person代碼塊 44 創建Person對象 45 執行Student代碼塊 46 創建Family對象 47 com.tca.thinkInJava.chap7.Student 48 創建student對象
1.首先在執行@test方法時,必須創建student的實例對象。
2.要創建student的實例對象,第一步先加載student父類person和student類的字節碼,並對相關靜態成員變量進行初始化,執行靜態代碼塊。
3.首先加載父類person字節碼,靜態成員變量public static family ,family優於靜態代碼塊前聲明,所以先對靜態成員變量family進行初始化。創建family對象,打印“創建family對象”,“xxxxxx”。
4.加載完person字節碼后,再加載student字節碼。靜態代碼塊再靜態成員public static family staticfamily之前聲明,所以先執行靜態代碼塊,打印“執行student靜態代碼塊”,在進行成員變量初始化,執行“創建family對象”,“xxxxxxxxxx”。
5.創建student父類person的實例對象,創建實例對象時,先進行非靜態成員變量初始化和代碼塊的執行,在執行構造器方法。所以先打印“執行person代碼塊”,再打印“創建person對象”。父類對象創建和初始化完畢。
6.創建子類對象student,先進行非靜態成員變量初始化和代碼塊的執行,在執行構造方法。代碼塊的聲明再非靜態成員變量聲明之前,所以先執行代碼塊,打印“執行student代碼塊”,再對family進行初始化,創建family對象,打印“創建family對象”,“xxxxxxxxxxx”。
7.執行test測試方法。
總結:
當不含static成員時,我們new一個對象A時,首先會先創建A類的父類B的實例對象,如果B類仍有C類,會先創建父類C的對象,以此類推,是一個遞歸創建的過程;當該類的父類對象已經全部創建並初始化時,會對該類進行創建和初始化。但在對該類進行初始化時,會先初始該類對象的成員變量,再執行該類的構造方法。成員變量的初始化和代碼塊的執行順序,由它們聲明順序決定的,按順序依次初始化或執行,但均在構造器方法之前執行。
當有static成員時,在該類第一次被JVM加載時,靜態成員變量只會被初始化一次,靜態代碼塊只會被執行一次。會先加載父類字節碼,再加載子類字節碼,如果有創建某類的實例對象,也是在該類的父類和該類的字節碼加載完成之后,才會實例化該類父類的實例對象和該類的實例對象。靜態成員變量的初始化和靜態代碼塊的執行順序,是由它們的聲明順序決定的,按順序依次初始化或執行。