什麼是類的初始化,什麼是類的實例化,什麼狀況下會觸發初始化,可能不少人都有這樣的疑問?java
那麼首先咱們須要瞭解一下jvm的類加載過程。面試
從JVM上來看,類的加載機制從加載到虛擬機內存到卸載出內存,分爲5個階段:裝載,連接(校驗,準備,解析),初始化,使用,卸載。jvm
這裏咱們只分析與咱們相關的幾個過程。函數
1,準備過程spa
例子
code
public class A{ (斷點) public static int a=1; public final static int b=2; public int c=3; } public class B{ public static void main(String args[]){ A.a=2; } }
賦值靜態域是咱們知道的四種觸發初始化的方法。繼承
那麼咱們在a變量前打斷點。內存
當執行main方法時,代碼第一次運行到斷點的位置時,你會發現get
a=0,b=2.沒有c。這就是類加載機制的準備階段。虛擬機
準備階段:內存分配靜態的類變量和常量.同時會爲靜態變量分配初始值。(分配初始值這個過程不少同窗都會忽略掉)
2.初始化階段
不少筆試或者面試都會問什麼狀況下會觸發初始化。
1,實例化的時候確定是要觸發的new 和Class.forName()
2,類的靜態方法被調用的時候
3,類的靜態域被訪問,被賦值的時候(若是訪問的是靜態常量,則不會觸發初始化)
4,java反射 reflect
大致就是這幾種方式。
初始化 會給靜態變量賦值,執行靜態代碼塊.
若是一個類有static{} 普通{} 構造器函數 A{}都有,還繼承了父類
則執行順序上來看,
例子
class A{ public static int a=1; static{System.out.println("1")} {System.out.println("3")} public A{System.out.println("4")} public static getA(){ System.out.println("7")} } class B extends A{ public static int a=1; static{System.out.println("2)} {System.out.println("5")} public A{System.out.println("6")} public static getA(){ System.out.println("8")} } public static void main(String args[]){ //new B;實例化子類 執行順序123456 //A.a=2 賦值父類靜態變量 ,執行12,a=2 //A.getA() 執行父類靜態方法 執行127 //B.getA() 執行子類靜態方法,和重寫沒毛關係,執行128 } 總結: 初始化只會執行靜態代碼塊,實例化會繼續執行普通代碼塊和構造函數。 }