1、類的成員變量、構造函數、成員方法的初始化過程
當一個類使用new關鍵字來創建新的對象的時候,比如Person per = new Person();JVM根據Person()尋找匹配的類,然后找到這個類相匹配的構造方法,這里是無參構造,如果程序中沒有給出任何構造方法,則JVM默認會給出一個無參構造。當創建一個對象的時候一定對調用該類的構造方法,構造方法就是為了對對象的數據進行初始化。JVM會對給這個對象分配內存空間,也就是對類的成員變量進行分配內存空間,如果類中在定義成員變量就賦值的話,就按初始值進行運算,如果只是聲明沒有賦初始值的話,JVM會按照規則自動進行初始化賦值。而成員方法是在對象調用這個方法的時候才會從方法區中加載到棧內存中,用完就立即釋放內存空間。
初始化過程:成員變量->構造函數->成員方法。
package com.yyq; /** * Created by Administrator on 2015-10-30. */ class Person { int age; String name; public Person() { System.out.println("This is Person()"); System.out.println("Name:" + this.name + "; Age:" + this.age); } public void show() { System.out.println("This is show()"); System.out.println("Name:" + this.name + "; Age:" + this.age); } } public class Exercise01 { public static void main(String[] args) { Person per = new Person(); per.show(); per.age = 30; per.name = "Wendy"; per.show(); } }
2、類的成員變量、靜態代碼塊、構造代碼塊、局部代碼塊、構造方法、成員方法的初始化過程
靜態代碼塊是在類中方法外成員位置出現,用了static修飾;一般用於給類進行初始化。靜態代碼塊在這個類第一次被調用或實例化的時候就會被執行。 靜態代碼塊只會執行一次,一般會用來初始化一些值,並且在所有對象中全局共享。構造代碼塊在類中方法外成員位置出現;可以把多個構造方法中共同的代碼放到一起,每次調用構造都執行,並且在構造方法前執行,對對象進行初始化。局部代碼塊在方法中出現,局部位置;限定變量的生命周期,及早釋放,提高內存利用率。
初始化過程:靜態代碼塊(只執行一次)->構造代碼塊(每次調用構造方法都執行)->構造方法。執行順序與代碼塊所在的具體位置無關。
局部代碼塊的初始化順序由具體位置決定。
package com.yyq; /** * Created by on 2015-10-30. */ class CodeBlockDemo { //靜態代碼塊 static { int a = 1000; System.out.println("靜態代碼塊1:"+a); } //構造代碼塊 { int x = 100; System.out.println("構造代碼塊1:"+x); } //構造方法 public CodeBlockDemo(){ System.out.println("Exercise02()"); } //構造方法 public CodeBlockDemo(int a){ System.out.println("Exercise02(int a):"+a); } //構造代碼塊 { int y = 200; System.out.println("構造代碼塊2:"+y); } //靜態代碼塊 static { int b = 2000; System.out.println("靜態代碼塊2:"+b); } } public class Exercise02{ public static void main(String[] args) { //局部代碼塊 { int x = 10; System.out.println("局部代碼塊1:"+x); } //出錯:找不到符號 //System.out.println(x); System.out.println("演示一---------------"); CodeBlockDemo ex1= new CodeBlockDemo(); System.out.println("演示二---------------"); CodeBlockDemo ex2 = new CodeBlockDemo(); System.out.println("演示三---------------"); CodeBlockDemo ex3 = new CodeBlockDemo(1); { int y = 20; System.out.println("局部代碼塊2:"+y); } } }
這里沒有將成員變量和成員方法加入分析,但是我們可以知道,靜態代碼塊在類加載的時候就已經初始化了,而成員變量是要在創建對象的時候才會根據構造方法進行分配內存,初始化賦值,所以如果你在靜態代碼塊中打印成員變量或者成員變量賦值的話就會顯示出錯,顯示要將變量類型改為static,而在構造代碼塊和構造方法中都能正常使用。
初始化過程:靜態代碼塊(只執行一次)->成員變量(每次創建對象都會初始化賦值)->構造代碼塊(每次調用構造方法都執行)->構造方法(每次創建對象都會調用相匹配的構造方法)->成員方法(對象調用的時候運行)。
3、有繼承關系的父類和子類的成員變量、構造方法、成員方法的初始化過程
在創建子類對象的時候會去調用子類的構造方法,其實子類的構造方法的第一條執行語句是super();即會自動去調用父類的無參構造方法,也就是說會自動去檢測子類所繼承的父類,並對父類的成員變量進行初始化操作。初始化完父類的成員變量、構造方法后,就初始化子類的成員變量和構造方法。因為子類會繼承父類的非私有成員變量和成員方法(這里我把成員變量和成員方法都定義為默認訪問權限),所以子類中如果定義了相同的成員變量,在初始化的時候就會被覆蓋,而成員方法在調用的時候如果父類有子類沒有,就執行父類的方法,如果父類沒有子類有就執行子類的方法,如果父類有子類也有的話,那子類的成員方法就是復寫了父類的成員方法,那最終執行就是子類的成員方法。
初始化過程:父類的成員變量->父類構造方法->子類成員變量->子類構造方法->父類/子類成員方法。
package com.yyq; /** * Created by Administrator on 2015-10-30. */ class Father{ int age = 40; String name = "Father"; int num = 321; public Father(){ System.out.println("Father()"); System.out.println("Name:"+name+"; Age:"+age+"; Num:"+num); } public void show(){ System.out.println("I am Father."); } public void play(){ System.out.println("Father play."); } }; class Son extends Father{ int age = 15; String name = "Son"; public Son(){ System.out.println("Son()"); System.out.println("Name:"+name+"; Age:"+age+"; Num:"+num); } public void show(){ System.out.println("I am Son."); } public void study(){ System.out.println("Son play."); } } public class Exercise03 { public static void main(String[] args){ Son son = new Son(); son.show(); son.play(); son.study(); } }
Father()
Name:Father; Age:40; Num:321
Son()
Name:Son; Age:15; Num:321
I am Son.
Father play.
Son play.
4、有繼承關系的父類和子類的成員變量、靜態代碼塊、構造代碼塊、構造方法,成員方法的初始化過程
因為如果有繼承關系的子類和父類,在創建子類對象的時候會自動的去調用父類的構造方法,對父類的數據進行初始化。但是如果父類和子類都有靜態代碼塊的話,那會先執行父類的靜態代碼塊,接着執行子類的靜態代碼塊,因為靜態代碼塊不需要創建對象才能執行,所以在加載類的時候首先運行靜態代碼塊,然后接着運行父類的構造代碼塊和父類的構造方法,最后才是運行子類的構造代碼塊和子類的構造方法。
初始化過程:父類靜態代碼塊->子類靜態代碼塊->父類構造代碼塊->父類構造方法->子類構造代碼塊->子類構造方法
package com.yyq; /** * Created by Administrator on 2015-10-30. */ class BaseClass{ static { System.out.println("靜態代碼塊BaseClass"); } { System.out.println("構造代碼塊BaseClass"); } public BaseClass() { System.out.println("構造方法BaseClass"); } } class SonClass extends BaseClass { static { System.out.println("靜態代碼塊SonClass"); } { System.out.println("構造代碼塊SonClass"); } public SonClass() { System.out.println("構造方法SonClass"); } } public class Exercise04 { public static void main(String[] args){ SonClass son1 = new SonClass(); System.out.println("-------------------"); SonClass son2 = new SonClass(); } }