從從語法的的角度來看,程序可以在3個地方對實例變量執行初始化:
定義實例變量時指定初始值非靜態初始化塊中對實例變量指定初始值構造器中對實例變量指定初始值其中第1、2種方式(定義時指定的初始值和非靜態初始化塊指定的初始值)比第3種方式(構造器中指定初始值)更早執行,但第1、2種方式的執行順序與它們在源程序中的排列順序相同。例如:public class Cat { //定義name,age兩個實例變量 String name; int age; //使用構造器初始化name,age兩個變量 public Cat(String name,int age) { System.out.PRintln("執行構造器."); this.name=name; this.age=age; } { System.out.println("執行非靜態初始化塊."); weight=2.0; } //定義指定初始值 double weight=2.3; public String toString() { return "Cat [name=" + name + ", age=" + age + ", weight=" + weight + "]"; }}public class InitTest { public static void main(String[] args) { Cat cat=new Cat("Kimy", 2); System.out.println(cat); Cat c2=new Cat("Migo",4); System.out.println(c2); }}console:執行非靜態初始化塊.執行構造器.Cat [name=Kimy, age=2, weight=2.3]執行非靜態初始化塊.執行構造器.Cat [name=Migo, age=4, weight=2.3]上面程序中的粗體字代碼代表java對象的3種初始化方式:構造器、初始化塊和定義變量時指定的初始值。每當程序調用指定構造器來創建Java對象時,該構造器必然會獲得執行的機會。除此之外,該類所包含的非靜態初始化塊將會獲得執行的機會,而且總是在構造器執行之前獲得執行。當程序執行①行代碼創建第一個Cat對象的時候,程序將會先執行Cat類的非靜態初始化塊,再調用該Cat類的構造器來初始化該Cat實例。注 意:很多讀者在看這個程序時可能會感到奇怪,會認為執行創建Cat對象后weight實例變量的值應該是2.0,而不是2.3。因為他們認為,double weight = 2.3;代碼應該先獲得執行。但實際上,定義變量時指定的初始值和初始化塊中指定的初始值的執行順序,與它們在源程序中的排列順序相同。定義實例變量時指定的初始值、初始化塊中為實例變量指定初始值的語句的地位是平等的,當經過編譯器處理后,它們都將被提取到構造器中。也就是說,對于類定義中的語句:double weight = 2.3;實際上會被分成如下2次執行。(1) double weight;:創建Java對象時系統根據該語句為該對象分配內存。(2) weight = 2.3;:這條語句將會被提取到Java類的構造器中執行。經過上面分析不難發現:定義實例變量時指定的初始值、初始化塊中為實例變量指定的初始值、構造器中為實例變量指定的初始值,三者的作用完全類似,都用于對實例變量指定初始值。經過編譯器處理之后,它們對應的賦值語句都被合并到構造器中。在合并過程中,定義變量語句轉換得到的賦值語句、初始化塊里的語句轉換得到的賦值語句,總是位于構造器的所有語句之前;合并后,兩種賦值語句的順序保持它們在源代碼中的順序。
新聞熱點
疑難解答