這裏只考慮在一個類的情況下類初始化和對象實例化的順序,不考慮有父類的情況下。
看下面這段代碼:
package com.huang.jvm;
/**
* @author hsz
*/
public class Demo {
int a = print(3);
public Demo() {
System.out.println("構造方法");
}
{
System.out.println("非靜態塊");
}
int b = print(4);
public int print(int value) {
System.out.println("實例" + value);
return value;
}
static int i = printStatic(1);
static {
System.out.println("靜態塊");
}
static int j = printStatic(2);
public static int printStatic(int value) {
System.out.println("靜態" + value);
return value;
}
public static void main(String[] args) {
new Demo();
}
}
執行結果如下:
靜態1
靜態塊
靜態2
實例3
非靜態塊
實例4
構造方法
Java虛擬機啓動時,會先對定義了main方法的類進行加載,而類加載過程會進行加載、驗證、準備、解析和初始化,而初始化過後就可以使用該類了。在準備階段中,虛擬機首先會爲類變量分配內存並賦初始值,int型的變量初始值是0,之後會在初始化階段爲變量賦予真正的要設置的值,並且也會執行static塊中的內容,至於哪個先執行,則看賦值操作和static塊的位置,哪個在前哪個先執行。所以以上的執行結果中依次打印出靜態1,靜態塊和靜態2。
注意:類加載在類的整個生命週期中只會進行一次,除非類卸載後又重新加載。
類初始化後就可以執行main方法中的代碼了。當遇到new Demo()時,會進行對象實例化。先爲成員變量賦默認的初始值(類似於類加載過程中的準備階段爲靜態變量賦初始值值),然後再按照成員變量以及非靜態塊的出現順序進行初始化,等所有成員變量初始化完成以及非靜態塊執行完之後調用構造方法完成對象的創建。每次new一個對象時都會執行一遍上面實例化的過程。所以類加載完後上面代碼的執行結果中先打印實例2,非靜態塊和實例4,最後在執行構造方法。