淺談 java對象的初始化【2012年7月25日 小冬分享】

java對象的初始化

小冬(珠海)11:02:48
我們知道一個對象可以有靜態變量、變量、靜態初始化塊、初始化塊,當我們創建一個對象時,它是怎麼初始化的呢?按什麼順序初始化的呢?
 
  1. public class Test { 
  2.  
  3.      
  4.     // 靜態變量 
  5.     public static String staticField = "靜態變量"; // 變量 
  6.     public String field = "變量"
  7.     // 靜態初始化塊 
  8.     static { 
  9.         System.out.println(staticField); 
  10.         System.out.println("靜態初始化塊"); 
  11.     } 
  12.     // 初始化塊 
  13.     { 
  14.         System.out.println(field); 
  15.         System.out.println("初始化塊"); 
  16.     } 
  17.     // 構造器 
  18.     public Test() { 
  19.         System.out.println("構造器"); 
  20.     } 
  21.     public static void main(String[] args) { 
  22.         Test test = new Test(); 
  23.  
  24.     } 
 
運行下代碼,輸出結果是:
靜態變量
靜態初始化塊
變量
初始化塊
構造器
 
 
由此可以看到,當new一個對象時,它並不是就是調構造方法,而是先初始化屬性變量,我們把變量的定義先後順序換下,再執行,會發現,靜態的是先於非靜態進行實始化的,那麼對於靜態變量和靜態初始化塊之間、變量和初始化塊之間的先後順序又是怎樣呢?是否靜態變量總是先於靜態初始化塊,變量總是先於初始化塊就被初始化了呢?
我們先改下代碼:
 
  1. public class Test { 
  2.  
  3.     public static TestA ta = new TestA(); 
  4.     // 靜態變量 
  5.     public static String staticField = "靜態變量"; // 變量 
  6.     public String field = "變量"
  7.     // 靜態初始化塊 
  8.     static { 
  9.         System.out.println(staticField); 
  10.         System.out.println("靜態初始化塊"); 
  11.     } 
  12.     // 初始化塊 
  13.     { 
  14.         System.out.println(field); 
  15.         System.out.println("初始化塊"); 
  16.     } 
  17.     // 構造器 
  18.     public Test() { 
  19.         System.out.println("構造器"); 
  20.     } 
  21.     public static void main(String[] args) { 
  22.         Test test = new Test(); 
  23.  
  24.     } 
  25.  
  26. class TestA { 
  27.     public TestA() { 
  28.         System.out.println("Test--A"); 
  29.     } 
 輸出是:
Test--A
靜態變量
靜態初始化塊
變量
初始化塊
構造器
 
 
靜態變量:static TestA ta = new TestA()在靜態初始化塊前,所以先輸出Test--A
再換下位置,把static TestA ta = new TestA()放到在靜態初始化塊後,我們發現輸出是:
靜態變量
靜態初始化塊
Test--A
變量
初始化塊
構造器
 
 
由此可見這是取決於它們在類中出現的先後順序,同理可得:變量和初始化塊之間也如此,總結可得:初始化優先級是(靜態變量/靜態初始化塊)>(變量/初始化塊)>構造器。
 
 
那繼承關係時的初始化又是怎樣的呢?如下:
大家應該知道,初始化子類時會先初始化父類,再看代碼:
 
  1. public class Test extends Parent{ 
  2.     // 靜態變量 
  3.     public static String staticField = "子類靜態變量"; // 變量 
  4.     public String field = "子類變量"
  5.     // 靜態初始化塊 
  6.     static { 
  7.         System.out.println(staticField); 
  8.         System.out.println("子類靜態初始化塊"); 
  9.     } 
  10.     //public static TestA ta = new TestA(); 
  11.     // 初始化塊 
  12.     { 
  13.         System.out.println(field); 
  14.         System.out.println("子類初始化塊"); 
  15.     } 
  16.     // 構造器 
  17.     public Test() { 
  18.         System.out.println("子類構造器"); 
  19.     } 
  20.     public static void main(String[] args) { 
  21.         Test test = new Test(); 
  22.     } 
  23.  
  24. class Parent{ 
  25.  
  26.     public String field = "父類變量";// 變量 
  27.     public static String staticField = "父類靜態變量"; // 靜態變量 
  28.     // 靜態初始化塊 
  29.     static { 
  30.         System.out.println(staticField); 
  31.         System.out.println("父類靜態初始化塊"); 
  32.     } 
  33.     // 初始化塊 
  34.     { 
  35.         System.out.println(field); 
  36.         System.out.println("父類初始化塊"); 
  37.     } 
  38.     // 構造器 
  39.     public Parent() { 
  40.         System.out.println("父類構造器"); 
  41.     }    
剛纔結果應該是:
父類靜態變量
父類靜態初始化塊
子類靜態變量
子類靜態初始化塊
父類變量
父類初始化塊
父類構造器
子類變量
子類初始化塊
子類構造器
 
從結果看到,並不是父類完全初始化完後再進行子類的初始化,子類的靜態變量和靜態初始化塊的初始化是在父類的變量、初始化塊和構造器初始化之前就完成了。
 
我們在main方法再創建一個對象,Test test2 = new Test();
大家就test2的初始化又如何?
 
爲了好看,我們子類構造器里加多行代碼System.out.println("***********");
輸出結果:
父類靜態變量
父類靜態初始化塊
子類靜態變量
子類靜態初始化塊
父類變量
父類初始化塊
父類構造器
子類變量
子類初始化塊
子類構造器
***********
父類變量
父類初始化塊
父類構造器
子類變量
子類初始化塊
子類構造器
***********


發現什麼了?
靜態變量和靜態代碼塊只加載一次 。
 
 
總結:
一、初始化優先級:
1、靜態變量/靜態初始化塊)>(變量/初始化塊)>構造器
2、父類>子類

二、靜態變量和靜態代碼塊只加載一次,因爲它們是全局共享的
 
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章